Using Multiple Properties Or The Entire Object In a Converter Class for Windows Phone and WinRT

Kind of a long wordy title, what does it really mean?  When you are creating a custom converter for Windows Phone or WinRT, you create a class that inherits from IValueConverter and implement a Convert method.  In that method you’re given (among other things) the value that has been bound (bind-ed sounds too funky, sorry) to your element and optionally a converter parameter that you can use to help you decide what your Convert method should return.  For example, your parameter could return “true”, “backwards”, “Blazers”, or whatever you want.  The main limitation as you may be noticing here is that you can only pass a single value back.  So what happens when you need to look at multiple properties of the item that is being used in the data binding in order to decide what to pass back from Convert? 

Here’s a simple example from something I was working on.  I’m binding to an item that has an “IsMine” and “IsOpen” property.  If the current item has “IsMine” equal to true, then I will return different values depending on whether IsOpen is true or false.  This obviously is not possible if you are just passing a single string back as your converter parameter.  The trick is to not assign a value to the binding; when you do that, the entire item is passed in as the “bind-ed” value.  So assume you’ve written a custom Convert method called MyColorConverter.  You want to use that for the background color of a Border element, so you would configure the binding for it like this:

 

<BorderBackground=”{Binding Converter={StaticResource DataItemsColorConverter}}”>

 

Notice that usually you would say what field you are binding too like this:  {Binding myField, Converter={blah}.  By omitting a specific field for the binding value, you get access to the entire object.  Then in my Convert method I can work with it like this:

 

    public class DataItemsColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {

            SharePointData.DataItem di = (SharePointData.DataItem)value;

 

            if (di.IsMine)
            {
                if (di.IsOpen)
                    return “#FF41719C”;
                else
                    return “#FFED7D31”;
            }
            else
                return “#FF7030A0”;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            //not going to be converting back
            return value;
        }
    }

 

 

How To Send An Authenticated Message to the Windows Phone Push Notification Service

The Push Notification Service is a cool feature of Windows Phone that lets you do things like send toast messages, update a Live Tile, etc. for your Windows Phone application.  You can use the service without any additional transmission security protocols, but if you do you are limited to a maximum of 500 messages per day.  If you use SSL to set up a mutually authenticated session to the Push Notification Service however, you can send an unlimited number of messages.  This makes securing your conversation that much more appealing.  The actual process for doing so is unfortunately documented about as poorly as anything I’ve ever seen.  Fortunately the social forums in the Windows Phone App Hub are quite useful so you can piece it together from reading through them.  To save you the time though of trying to hunt down all of the pieces needed to do this, I thought I would bring it all together here in one simple document.  You know, kind of like the product team should have done.  🙂  So here goes:

  1. You can read about the requirements for the certificate that’s used for establishing this secure communication here:  http://msdn.microsoft.com/en-us/library/ff941099(v=vs.92).  To make it simple though, I found that if you have an SSL certificate from one of the supported certificate authorities, it works just fine.  To see the list of supported certificate authorities, see here:  http://msdn.microsoft.com/en-us/library/gg521150(v=vs.92).
  2. You need to take this certificate and upload it to the App Hub.  You don’t need the PFX with the private key, just the public version of the certificate (i.e. the .cer file).  To upload it, sign into the App Hub, sign-in and then click on your account name in the upper left corner.  When you go into the account management page you will see a link called Certificates under the My Account banner.  Click on that and follow the instructions there to upload the certificate.
  3. In your Windows Phone application you create a HttpNotificationChannel class instance.  When you create the new HttpNotificationChannel, use the common name (CN) of the SSL certificate as the second parameter for the new channel.  You can find the common name of your certificate by double-clicking on the .cer file top open it, click on the Details tab, and then click on the Subject property.  You will see values displayed in the window below and the first one should be something like “CN = www.contoso.com“; you want to use just the “www.contoso.com” in this example.  So when you created your new channel it would look something like this:  pushChannel = new HttpNotificationChannel(“myChannelName”, “www.contoso.com“);
    1. NOTE:  If you have already created channels for different devices, then you will need to find your channel using the HttpNotificationChannel.Find method, then .Close and .Dispose the channel.  Then you need to recreate it so you can associate your common name with the connection.
  4. Where run your server side code, you need to install the certificate, including the private key (so the .pfx file).  You also need to ensure that the account for your application pool has access to the private keys for that certificate.  To do that, open the MMC tool and add the Certificates snap-in for the Local Computer.  After you’ve installed your certificate into the Personal node, right-click on the certifcate in the MMC and select All Tasks…Manage Private Keys.  You then need to add the account for the application pool your application is using and grant it at least Read rights to the keys.
    1. NOTE:  If you are using the new built in accounts in IIS 7.5, like ApplicationPoolIdentity, then you need to grant access to IIS apppool\ASP.NET v4.0, where “ASP.NET v4.0” is the name of your app pool.
  5. In the code where you are sending the message to the Push Notification Service you need to add the certificate to the HttpWebRequest object.  You would typically do this by opening up the X509 Store, getting the certificate collection for the My store, doing a Find on the collection by thumbprint, where you need to copy and paste the certificate’s thumbprint from the certificate properties to your code, and then using the first certificate in the collection it returns (i.e. myCollection[0]).  Once you have the certificate you can add it to your request like this:  myRequest..ClientCertificates.Add(mySslCertificate);

The other important things to note:

  • Your certificate that you upload in only used for four months.  If you don’t submit an application for certification to the marketplace that uses the certificate then it will need to be uploaded again.  When you submit your app for certification to the marketplace you will have an opportunity to select a certificate for it from the list of certificates that you have uploaded.  Just select the certificate that you uploaded for these communications and you are set.
  • How do you know if this works?  Well, when you create the HttpNotificationChannel class instance on the Windows Phone client, you will get back a notification channel Uri that send your messages to.  Look at that Uri – if you are not using an authenticated connection, then you will see “throttledthirdparty” in the path.  However if you created your class instance correctly, the path will contain “unthrottledthirdparty”; in addition the protocol it shows will be HTTPS instead of HTTP.  Now of course, to really make sure it works, after you get that Uri back you need to successfully send a message.  If it arrives at your device okay then you know it worked.

Using Compression on Windows Phone 7.5

As I’m sure many of you know who have done development on Windows Phone, there isn’t built in support for compression and decompression.  Many folks have pointed to the SharpCompress project on CodePlex, and this is what I ended up using for it as well.  The BIG thing that was missing from it though has been any documentation whatsoever for decompressing files on the phone.  I had quite a bit of code I had written for a winform application that used the WriteAllToDirectory method to decompress a zipped file on Windows.  However, that method doesn’t exist in the assembly for Windows Phone.  In addition, you can’t just provide the path to which you can unzip when using the Windows Phone assembly for SharpCompress, you have to give it a stream object.

This ultimately worked, but requires you to do things quite a bit differently from when you use this on the full version of Windows.  Here are some tips to get you through this:

    1. Enumerate through the Entry collection of the IReader  you get from the Reader factory:

      //”sr” is a stream reader object from previous code that contains the byte array of the actual zip file

      using (var reader = ReaderFactory.Open(sr))

      {

      while (reader.MoveToNextEntry())

      {

         //IsDirectory always returns false in everything I’ve seen so far

         if (!reader.Entry.IsDirectory)

         {

            //process the entry, described next

         }

         else

         {

             //do not know of a scenario where we can end up here

             Debug.WriteLine(reader.Entry.FilePath);

         }

      }

      }

        2.       Create the directory(s) for the files, then get an IsolatedStorageFileStream instance to which you can write:

        //IsDirectory always returns false in everything I’ve seen so far

        if (!reader.Entry.IsDirectory)

        {

               IsolatedStorageFileStream theFile = GetLocalFile(reader.Entry.FilePath);

        }

         

        private IsolatedStorageFileStream GetLocalFile(string fullPath)

        {

           IsolatedStorageFileStream fs = null;

         

           try

           {

               //get isolated storage so we can create directories and decompress

               IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();

         

               //trim everything from the last index of /, which is the file

               //name, i.e. it will look like folder/folder/folder/filename.txt

               string dirPath = fullPath.Substring(0, fullPath.LastIndexOf(“/”));

         

               //what’s nice is you can create the full folder path in one call

               if (!storage.DirectoryExists(dirPath))

                  storage.CreateDirectory(dirPath);

         

               //now that all the directories exist, create a stream for the

               // file – again, cool because you can just give the full path

               fs = storage.CreateFile(fullPath);

           }

           catch (Exception ex)

           {

               Debug.WriteLine(ex.Message);

           }

         

           return fs;

        }

          3.       Now that you have a stream, you can write the individual file out use the WriteEntryTo method:

            if (!reader.Entry.IsDirectory)

            {

               IsolatedStorageFileStream theFile = GetLocalFile(reader.Entry.FilePath);

             

               if (theFile != null)

                   reader.WriteEntryTo(theFile);

            }

             

            Hope this helps someone, the lack of documentation was troublesome so I just had to puzzle through it.

            Deciphering NullReferenceException or Binding Reference Cycle Errors in Windows Phone 7.1

            I recently ran across a very, very difficult problem to diagnose and fix, and I couldn’t find this issue going on anywhere else so I thought I’d write about it here in case it comes up again for anyone else.  In a Windows Phone 7.1 (i.e. Mango) application, you have a service reference – in my case, a WCF application.  What I was seeing is that frequently yet randomly, it would throw an exception just creating the WCF proxy.  What I mean by that is this line of code:

            MyService.MyClass foo = new MyService.MyClass(“myConfigSettings”);

            Would throw an exception.  While that’s kind of inherently crazy, what was more puzzling and frustrating about it is that the exception it would throw wasn’t always the same.  It would throw one of these two exceptions – no rhyme or reason as to which it would throw when:

            • NullReferenceException – absolutely no details here, no message, no inner exception nothing.
            • A binding reference cycle was detected in your configuration. The following reference cycle must be removed: basicHttpBinding/BasicHttpBinding_IMyAppInterface

            One of the (many) nutty things about this, is that the exception would only be thrown when the method was invoked from some code that ran during application start up; invoke that method any other time and there’s no problem.  Also, if you just step through the exception handling code and then drag the next line of execution back up to create the proxy instance, it always worked.  There were other really strange and weird things that had varying degrees of success, but what finally kind of tipped it off to me was the fact that in the application start up code, there was another chunk of code that executed and it also created an instance of that WCF proxy and it NEVER failed.  So in trying to figure out why one always worked and one frequently failed, it finally occurred to me to look at how the code was being invoked.  As it turns out, I had two different background threads being created, and each one was running a different chunk of code.  Each thread was both calling different methods that contained code that would instantiate an instance of the WCF proxy.  Well this, as it turns out, was the downfall and cause of this little problem.  By reconfiguring the code so that all the app startup tasks run on a single background thread, the weird exceptions magically disappeared.

            It was pure luck of course figuring this out (along with a lot of trial and error) so I thought I would share this little nugget in case you find yourself in a similar predicament.

            Windows Phone 7 and Other Mobile Device Access to SharePoint 2010 SAML Sites After Applying SP1 and June 2011 CU

            As I alluded to in an earlier post, there have been some changes in SP1 and June CU that impact the ability of Windows Phone 7 (both RTM and Mango) and other mobile devices to access SharePoint sites that use SAML authentication.  I described in a different post how to change the compat.browser file to essentially change the behavior when entering a SAML site so that it treats a mobile browser as a regular desktop browser (http://blogs.technet.com/b/speschka/archive/2010/11/21/some-windows-phone-7-and-sharepoint-2010-tips.aspx).  That at least lets you authenticate with the site, and then you can use the normal browser views of the site or you can manually navigate to the mobile pages.

            When SP1 and June CU came out however, the method of modifying the compat.browser file to allow authentication quit working.  Since that time a number of folks have looked at this and for now there is a new work-around that will provide the same behavior as before.  To do this, you need to modify the web.config file for each web application that you intend to use your mobile devices on.  To get this behavior add the following snippet in the system.web section of the web.config of your Web Application:

            <browserCaps>

            <result
            type=”System.Web.Mobile.MobileCapabilities, System.Web.Mobile,
            Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” />

            <filter>isMobileDevice=false</filter>

            </browserCaps>

            Making this change should allow most mobile devices to access a SAML secured site.  It does not, however, enable the Office Hub application in Windows Phone 7 to work with the site.  If or when the story changes on mobile support I’ll update the blog with another post.

            Connecting to an SSL WCF Service with Windows Phone 7 Emulator

            Had lots of fun earlier trying to figure out why my Windows Phone 7 application could not connect to my WCF endpoint.  I had tested things out thoroughly with a standard winforms client application and everything worked great, but whenever I tried hitting the same endpoint from my WP7 emulator I’d get the annoying error along the lines of “no endpoint listening” and if you look at the inner exception it was something like a 404 not found response.  Of course this was completely silly, the endpoint was there.  There were two things that I learned to resolve this:

            1. The error really meant that the phone emulator did not have the root certificate authority for the SSL cert in its list of trusted certs.  Unfortunately even with the WP7 1.1 (i.e. Mango SDK), there does still not appear an easy way to do this.  What you really need to do is put the root CA .cer file into a zip file somewhere, and then put it up on a web site where you can download it.  It could be a local development server, you can email it to yourself at something like HotMail, etc.  Navigate to that file from within the emulator and it will download it then show you the contents of the zip file.  If you click on the .cer file then it will offer to install it for you.  Take it up on this offer and it will put it in the list of trusted certificate authorities and you are good to go.  Or so it may seem… (see the next item)
            2. The steps I described in #1 work great…until you stop and restart the emulator.  It has no persistent state it seems so everytime you happen to stop it (or the many times it gets stopped itself and/or disconnected from Visual Studio) you have to repeat step 1 all over again.  Every time.  Painful as heck.  Not sure if this is on the fix radar or not but I guess we’ll see.

            FBA Sites with Office Hub in Windows Phone 7

            Hey all, just wanted to give a quick but important update to the post on integrating SharePoint 2010 with Windows Phone 7 (http://blogs.technet.com/b/speschka/archive/2010/11/21/some-windows-phone-7-and-sharepoint-2010-tips.aspx).  After playing around with this some more and reviewing some of the tips left in the comments by our friend Tomislav, I got the right combination of things to get the Office Hub in Windows Phone 7 to open an FBA site. 

            There were two keys to making this work as it turns out:

            1. You must secure your FBA site with SSL.  If you don’t have SSL then you won’t have joy.
            2. You must use a fully-qualified domain name for the zone.  For example, https://foo will NOT work.  However, https://foo.contoso.com WILL work.  This was the important distinction I found in my testing.

            Hope this clears up some of the ongoing confusion around Office Hub support for FBA sites in SharePoint 2010.  Thanks to all the folks who commented on the previous thread; I think it’s been very helpful to everyone that’s trying to figure this all out right now.

            Some Windows Phone 7 and SharePoint 2010 Tips

            Now that I’ve finally got my Windows Phone 7, I have had a little time to play around with some of the integration with SharePoint and start to understand better some of the issues and limitations I’ve heard described previously by other folks.  I’m going to try and share some of those details here so hopefully you will be clearer on what does and does not work right now and what you can do to mitigate in certain circumstances.

            First, as an aside, I must say that I am really very impressed with Windows Phone 7 (hereafter referred to as WP7).  Like many folks at my current employer, I’ve only had a Windows Phone since they first came out, up to and including the Windows Mobile 6.5.  I’ve had more than my share of frustrations and was getting ready to just jump ship myself here not that long ago, when I got wind of the WP7 release date.  Since it was only a few months away I decided to hold out one more time and give it a try, and boy am I glad I did.  To begin with, I purchased the Samsung Focus.  Folks, the display on this phone is amazing – really fantastic.  It’s like looking at a minature high def device, the picture is so bright and clear.  Kudos to Samsung on the device.  The phone itself has a few annoyances as most devices do, but overall the performance and functionality is really terrific.  Texting has never been easier.  I’ve thought for the last several years that I must have disproportionately large thumbs compared to the rest of the humans because I always had so many typos in messages, which made for a long and frustrating experience creating messages.  The new auto-correct feature in WP7 is really, truly amazing.  I don’t know who developed this stuff but I highly recommend that they start working on the next manned space launch to Mars or something because the work these guys have done is brilliant.  The whole touch screen experience is also extremely fluid and easy to use – waaaayyyyy better than anything that was in Mobile 6.5.  The integration with Zune is definitely cool – I’ve already synced a bunch of music from my PC to my phone, and the integration with XBox Live is cooler yet.  It’s awesome seeing my little XBox Live Avatar on my screen, as well as being able to check out my latest accomplishments, etc.  And that’s not even mentioning the wide array of games that I can get on my phone now (note to wife:  my bill may be uncharacteristically high this month).  Also, the performance is SNAPPY!  It is SO much better than Mobile 6.5 in that respect.  Anyways, I could go on and on but I won’t, I’m not really a product reviewer but have been so impressed with this device and OS that I felt compelled to share.  Now, onto the subject at hand.

            The first thing I want to differentiate here is the difference in what you can do with SharePoint on WP7 in the browser, versus with the Office hub (a.k.a. SharePoint Mobile Workspace).  Let’s start with the browser.

            Overall, most SharePoint sites work great in the WP7 browser.  One thing that is kind of interesting is that even if you configure your browser in WP7 to be the mobile version vs. the desktop version, when you hit a SharePoint site it will always display the full browser version.  If you want to see the mobile version of a site in SharePoint 2010 you must append the querystring “?mobile=1” to the end of your Url.  Note that this is different from SharePoint 2007 where you just append a “/m” to the Url to get the mobile views; if you try and do the same thing in SharePoint 2010 it will give you a page not found error.  As far as the mobile views themselves, they are definitely improved and look much nicer in 2010 than they did in 2007.  Now, here’s the one big funky thing to be aware of, and of course it has to do with claims web sites in SharePoint.  I also need to scope my comments – in my claims sites in my lab, they are configured to authenticate with AD FS 2.0.  My ADFS server is configured to use Windows authentication.  Since I use the fully-qualified name of my ADFS server, the browser doesn’t attempt to send my credentials automatically; instead it gives me the standard browser Windows auth prompt.  Okay, so – in the WP7 browser, this does not work.  I can get to the site where I select my authentication type (Windows or my SPTrustedIdentityTokenIssuer).  I select SAML auth provider and it redirects me to ADFS, but at that point things fail.  What I mean by “fail”, is that the browser doesn’t throw out that Windows authentication dialog, so I never get past the ADFS site.  If you are looking at the WP7 browser it effectively looks like it’s frozen, but it really isn’t.  Fortunately my friend Joe F. gave me a way to fix this so I will share it here.  You need to go in and modify the compat.browser file.  That means you need to visit every WFE, and drill down to where the compat.browser file is.  By default it’s in the \inetpub\wwwroot\wss\VirtualDirectories\yourVirtualDirectory\App_Browsers folder.  In there you want to find the entry for the Windows Phone 7 browser agent – the user agent is Office Mobile Web Access.  You want to find the isMobileDevice attribute of the capabilities element and change it from “true” to “false”.  That will also recycle your IIS virtual server, but now you should be able to navigate to the site in your WP7 browser.  This time though when you hit the ADFS site you should get an authentication prompt in WP7 in which you can enter your credentials and continue.  Again, I’m reporting the “simplest” ADFS implementation; depending on what kind of authentication you’ve implemented there, your mileage may vary.

            Now, let’s talk about the Office hub.  The Office hub in WP7 is really pretty slick and a nice user experience.  However…for now you are pretty limited in terms of the SharePoint sites you can hit.  Folks, I’ll just come out and say it, but in my testing (and this is pretty consistent with what I had heard elsewhere), you will only be able to use the Office hub on SharePoint sites that are configured to use Windows authentication and are in the equivalent of the intranet zone.  For example, I have a site called http://farm2 that uses Windows claims auth and I can open it and all the documents in it just fine in Office hub.  However, I also have a site called http://wcftest.vbtoys.com and it also uses Windows auth, but I cannot access it from Office hub.  When I try I get an error message that says “Can’t open…SharePoint doesn’t support this authentication scheme.”  Well the real problem here is that the browser, just like IE on the desktop, sees the period (“.”) in the Url and that puts in in the Internet zone.  Here the problem is that in the Internet zone, the Office hub does not support Windows authentication.  So now I’m basically cut off from that site on my WP7.

            Here’s another example:  in this case, I’m trying to hit a site that should be in the “Intranet” zone – the Url is https://fc1.  The site is configured to use both Windows and SAML claims.  Well, unfortunately the SAML claims part won’t work with Office hub either.  So you still get the same error message I described above.  If you try a site that is only SAML auth, you hit the same problem – no entry.  I thought it would be curious to see if the Office hub could re-use the FedAuth cookie from the WP7 browser, so I made the compat.browser change I described above and navigated to my SAML sites in the browser.  Then I tried opening them up again in Office hub and…no joy – same error message. 

            Finally, for completeness, I tried a SharePoint site secured with FBA claims.  The net of it is you get a slightly different error, but you still don’t get in.  In this case you get an error message that says “Can’t open…SharePoint doesn’t support non-SharePoint servers and can’t open the requested content.  You can try opening the content in your web browser instead.”  And it gives me a nice “open” button that if clicked will indeed open the SharePoint site in my browser…but not in Office hub.

            So that’s what I’ve found so far.  The WP7 overall is really great, the SharePoint integration with the browser is pretty good, but with Office hub it is lacking.  Hopefully though you at least know what you have to work with now and can plan accordingly and/or plug in some other authentication mechanism in-between you and site (like UAG) if you want to open up more of your sites to Office hub.