Uploading an Image to Facebook in Windows Phone 7 (Silverlight)

No Comments »

This is a full-featured tutorial, walking through design, structure, UI and photo formatting. If you just want to know how to get from a Windows Phone 7  PhotoResult to posting that photo to Facebook, skip down to “Capture and Format the Photo” and start from there.

This post assumes you’ve gone through the process of setting up the permissions for a Facebook app and getting your user to log into Facebook through your app. In short, it assumes you’ve walked through this tutorial.

For this tutorial, I’ve re-jiggered the code into a more formal MVVM structure. I’m using MVVM Light because I am familiar with it. I would highly recommend it.

Download Facebook Message in Windows Phone 7 project files

Make sure you go to the App.xaml.cs file to change the FacebookAppID and FacebookAppSecret to fit your particular needs.

Design Considerations

When uploading an image either from the camera or from a saved image, we want to make sure the user has an good experience with it. This post will cover:

  • Taking the picture
  • Displaying the picture so the user can verify they picked the right one.
  • Adding a message (caption) to the picture.
  • Formatting that picture for a Facebook update.
  • Committing the update.

Setting Up Our Properties

We will set the following properties to be non-bindable (basic private properties)

PhotoResult _rawPhotoResult – this is what we get back from our phone when we take or select a picture. Rather than separate the bits out of it, we’ll just hold onto it in the view model for reasons that will soon become clear.

byte[] _fbImageHolder – this is the byte array of the image the user has selected. This is what we’ll upload to Facebook when we’re ready, but we wouldn’t use this to show to the user.

We’ll have the following Bindable properties (a property that implements that raises the PropertyChanged event when updated.

BitmapImage FBImagePreview – We can bind a BitmapImage to our UI, so we’ll use this BitmapImage to show the user what they are uploading.

string FBImageMessage – This is the caption for the image. We’ll use a TwoWay binding between this and a TextBox so the use can easily add some text.

bool HasImage – When the user opens the app, they won’t have an image selected, so we’ll want to show them some UI elements that let them start the selection process. HasImage will make that happen.

bool IsImageLoading – When the user opens the app, they won’t have an image selected, so we’ll want to show them some UI elements that let them start the selection process. HasImage will make that happen.

ICommand ProcessImageResult – We’ll call this when we come back from getting the photo. It will handle all the photo-crunching we need to see a preview of the image as well as put the image into our _fbImageHolder byte array.

ICommand CommitFacebookPhoto – This will do the actual commit of the image and the text to Facebook.

Setting Up Our UI

The biggest part of this UI is that we want the user to add a photo when there isn’t one and then see the photo when it is there.

For this, we’ll add a image to hold the FBImagePreview binding and a button to take the picture. We’ll turn the visibility for these elements on and off based on the “HasImage” property and we’ll add an event handler to Button so our XAML looks like this:

<Image Visibility="{Binding HasImage, Converter={StaticResource BoolToVis}}"
        Source="{Binding FBImagePreview}"
        Width="300"
        Height="300"
        HorizontalAlignment="Left"
        Margin="12,0,0,0" />
<Button Visibility="{Binding HasImage, Converter={StaticResource RevBoolToVis}}"
        Content="take or select picture"
        Width="300"
        Height="300"
        HorizontalAlignment="Left"
        Click="TakePicture"/>

We’ll deal with getting the picture in a moment. For now, we’ll just also make sure we have a TextBox set to the FBImageMessage binding and the Button bound to our CommitFacebookPhoto command. (I walked through how to set a command to an event in the previous Facebook tutorial post, so I won’t re-write it here.) Instead, I’ll just show the code I used for the TextBox and Button:

<TextBox TextWrapping="Wrap"
    Text="{Binding FBImageMessage, Mode=TwoWay}"
    MinHeight="175"/>
<Button Content="post image to wall"
        Visibility="{Binding HasImage, Converter={StaticResource BoolToVis}}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <GalaSoft_MvvmLight_Command:EventToCommand
                Command="{Binding CommitFacebookPhoto, Mode=OneWay}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

Capture and Format the Photo

In our “take or select picture button”, we call the “TakePicture” method in our code-behind. Here, we run standard code for getting or selecting an image.

private PhotoChooserTask _pct;
private void TakePicture(object sender, RoutedEventArgs e)
{
    _pct = new PhotoChooserTask();
    _pct.ShowCamera = true;
    _pct.Completed += new EventHandler<PhotoResult>(_pct_Completed);
    _pct.Show();
}

Using the PhotoChooserTask with ShowCamera set to true means the user can either select a previously taken photo or take a new one. We set the Completed event handler and show task.

When the user has selected the image, we go to this event handler:

void _pct_Completed(object sender, PhotoResult e)
{
    if (e.Error == null)
        _viewModel.ProcessImageResult.Execute(e);
    else
        MessageBox.Show("Make sure your phone isn't plugged into your computer before you add a picture.",
                        "No picture loaded",
                        MessageBoxButton.OK);
}

For this to work, we’ll use a pretty standard trick in MVVM programming, which is to add the following in the View code behind so that we can call commands from code. Handy in situations exactly like this:

private MainViewModel _viewModel { get { return (MainViewModel)DataContext; } }

Inside the ProcessImageResult command, we want to set the FBImagePreview so that our user can see it and also get the _fbImageHolder byte[] ready so we’re all set to commit the image.

public ICommand ProcessImageResult
{
    get
    {
        return new RelayCommand<PhotoResult>(result =>
        {
            _rawPhotoResult = result;
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                FBImagePreview = new BitmapImage();
                FBImagePreview.SetSource(result.ChosenPhoto);
                HasImage = true;
            });
            _fbImageHolder = ImageHelpers.FacebookImagePrep.SimpleFacebookPhotoCrunch(result.ChosenPhoto, 720, 0);
        });
    }
}

In the full project, you’ll see a more involved version of the image prep in which I use EXIF data to properly rotate the image. (Thanks to Tim Hueur for lighting the way on that count.) But for now we’ll just walk through a simple way to convert an image Stream to a byte[].

using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.Windows.Controls;
using System.IO;
public static byte[] SimpleFacebookPhotoCrunch(Stream chosenPhoto, double maxSize, int rotation)
{
    // Set a BitmapImage using the source stream
    BitmapImage bmp = new BitmapImage();
    bmp.SetSource(chosenPhoto);

    // The largest permissable Facebook image upload is 720px (soon to be 920px)
    //    This finds if the image width or height is largest and sets the resize
    //    information accordingly
    double resizeRatio = 1;
    int resizeHeight = bmp.PixelHeight;
    int resizeWidth = bmp.PixelWidth;
    if (Convert.ToDouble(bmp.PixelHeight) > maxSize || Convert.ToDouble(bmp.PixelWidth) > maxSize)
    {
        if (bmp.PixelHeight > bmp.PixelWidth)
        {
            resizeRatio = maxSize / Convert.ToDouble(bmp.PixelHeight);
            resizeHeight = Convert.ToInt16(resizeRatio * Convert.ToDouble(bmp.PixelHeight));
            resizeWidth = Convert.ToInt16(resizeRatio * Convert.ToDouble(bmp.PixelWidth));
        }
        else
        {
            resizeRatio = maxSize / Convert.ToDouble(bmp.PixelWidth);
            resizeHeight = Convert.ToInt16(resizeRatio * Convert.ToDouble(bmp.PixelHeight));
            resizeWidth = Convert.ToInt16(resizeRatio * Convert.ToDouble(bmp.PixelWidth));
        }
    }

    // The default WriteableBitmap class lets us use a very simple
    //   resize/rotation/quality JPEG extension and lets us output that as a byte[]
    WriteableBitmap writeBmp = new WriteableBitmap(bmp);
    using (MemoryStream ms = new MemoryStream())
    {
        Extensions.SaveJpeg(writeBmp, ms, resizeWidth, resizeHeight, rotation, 100);
        return ms.ToArray();
    }
}

And that’s it! Our photo shows up in the UI for preview and we are ready to send the photo to Facebook.

Sending the Photo To Facebook

We should have the button command already set up for that, so all we need to do is write the details into the command.

public ICommand CommitFacebookPhoto
{
    get { return new RelayCommand(() => {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                IsImageLoading = true;
            });
            var facebookUpload = new Facebook.FacebookMediaObject
            {
                FileName = Guid.NewGuid() + ".jpg",
                ContentType = "image/jpg"
            };
            facebookUpload.SetValue(_fbImageHolder);
            var photoDetails = new Dictionary<string, object>();
            photoDetails.Add("message", FBImageMessage);
            photoDetails.Add("image", facebookUpload);

            _asyncFbClient.PostCompleted += new EventHandler<FacebookApiEventArgs>(_asyncFbClient_ImagePostCompleted);
            _asyncFbClient.PostAsync(@"/photos", photoDetails);

        });
    }
}

First, we turn on “IsImageLoading” so the user knows the app is  hard at work on this. Then we create a new FacebookMediaObject and set the value to our byte array. We set the details so Facebook knows we’re sending both a message and an image, then we add an event handler to handle the results. And away we go.

In our event handler, we check to see if the user cancelled the request (normally done by turning the phone off or otherwise disabling the app before the upload can complete) of if there were any other errors. If everything went right, we clear out the UI so the user can add another image if they so desire.

void _asyncFbClient_ImagePostCompleted(object sender, FacebookApiEventArgs e)
{
    _asyncFbClient.PostCompleted -= _asyncFbClient_ImagePostCompleted;
    if (!e.Cancelled) {
        if (e.Error != null) {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                MessageBox.Show("Crap. Something went wrong and it was: " + e.Error.Message);
                IsImageLoading = false;
            });
        } else {
            _fbImageHolder = null;
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                FBImagePreview = null;
                FBImageMessage = "";
                HasImage = false;
                IsImageLoading = false;
            });
        }
    } else {
        Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            MessageBox.Show("Request was cancelled before upload could complete.");
            IsImageLoading = false;
        });
    }
}

And that’s the end!


Posting To The Facebook Wall in Windows Phone 7 (Silverlight)

1 Comment »

This post assumes you’ve gone through the process of setting up the permissions for a Facebook app and getting your user to log into Facebook through your app. In short, it assumes you’ve walked through this tutorial.

For this tutorial, I’ve re-jiggered the code into a more formal MVVM structure. I’m using MVVM Light because I am familiar with it. I would highly recommend it.

Download Facebook Message in Windows Phone 7 project files

Make sure you go to the App.xaml.cs file to change the FacebookAppID and FacebookAppSecret to fit your particular needs.

This is a full-featured tutorial, running through the view model and view setup for properly sending a Facebook message. If you just want to see the code for sending the message, skip down to “Sending the Facebook Message” at the bottom.

Setting Up Our Properties

Doing this the MVVM way is actually pretty simple. We’ll set up some properties in our view model and use those properties to drive our UI.

We will need:

FacebookMessage – string – This will hold the string message we want to post to Facebook.

IsLoadingMessage – bool – We’ll turn this on when the message is sending and turn it off when we’re done.

SendFacebookMessage – ICommand – We’ll execute this command when we’re ready to send the message out.

Setting Up Our UI

Again, very simple. We are going to add a ScrollViewer (I like to use ScrollViewers whenever the user might be typing so they can still see other bits of the screen) and put the rest of the stuff in there. We’ll add:

 1: <TextBox TextWrapping="Wrap"
 2:             Text="{Binding FacebookMessage, Mode=TwoWay}"
 3:             MinHeight="175"/>

 

We want the text to be bound to the message we’re going to send and the TwoWay mode makes sure that any updates we make in the UI are automatically synced with the view model property. I’m using a MinHeight as a way of implying to the user that this could be a multi-line message. Basically just prepping them for what kind of interaction to expect.

 1: <Button Content="post to wall"/>

 

We’ll use this button to run the command that starts all the work. The super-awesome way to do this is to go to the “Assets” tab in the top left corner of the screen, select “Behaviors” and drag an “EventToCommand” behavior onto your button.

image

select the EventToCommand behavior on the button and you should see on the right properties that can be set on that behavior. Click on the “Advanced options” (the little gray box next to the Command property”) and select “Data Binding”.

image

The Create Data Binding window will pop up. If you don’t see your command in the fields section, rebuild your project from Blend (under the Project menu) and it should refresh.

image

Select the SendFacebookMessage command and double check to see that the “EventName” is set to “Click”.

image

That should be the default, but it’s good to make sure.

Finally, we’re going to put together some UI for the user to get some feedback while the app is updating Facebook. We want two things:

  1. Not hit the button several times or change the message while it’s updating. In general, just leave everything alone.
  2. See that an update is happening.

In this project I did this very simply. First, I added some UI to cover all the elements (named “InteractionBlocker”).

 1: <Grid x:Name="InteractionBlocker"
 2:       Grid.Row="1"
 3:       Margin="0,48,0,0"
 4:       Background="#97000000"
 5:       Visibility="{Binding IsLoadingMessage, Converter={StaticResource BoolToVis}}"
 6:       />

 

When a message is updating, this grid simply covers the elements. It is semi-transparent, so the UI just goes a little dark while the update is being made. I’m using a BoolToVis converter, which can be used in a binding to convert a boolean value into a visibility value. Here is Kent Boogaart’s version of it, which isn’t the version I use, but works great none-the-less. (My version is in the project if you’re really interested.)

To let the user know that an update is going on, we’ll use a ProgressBar.

 1: <ProgressBar
 2:     Margin="0,4,0,0"
 3:     Grid.Row="1"
 4:     VerticalAlignment="Top"
 5:     Visibility="{Binding IsLoading, Converter={StaticResource BoolToVis}}"
 6:     IsIndeterminate="{Binding IsLoading}"
 7:     />

 

Here, we just set it to crawl across the top of the screen when we’re loading our message. We hide it and show it based on whether the user needs to see it. Pretty simple. (If you’re working on a big Windows Phone project, download and install the Silverlight Toolkit, which has a Progress bar that plays much nicer with your app performance. The default ProgressBar is good enough for our current needs.)

Sending the Facebook Message

We’ll do all our calls in the ICommand we’ve set up. When the user logged in, we created a private FacebookClient object with our access token, so we’ll just go ahead and use that.

 1: public ICommand SendFacebookMessage
 2: {
 3:     get { return new RelayCommand(() => {
 4:             var parameters = new Dictionary<string, object>
 5:             {
 6:                 {"message", FacebookMessage},
 7:                 {"privacy", new Dictionary<string, object>
 8:                     {
 9:                         {"value", "ALL_FRIENDS"}
 10:                     }
 11:                 }
 12:             };
 13:             _asyncFbClient.PostCompleted += new System.EventHandler<FacebookApiEventArgs>(_asyncFbClient_PostCompleted);
 14:             _asyncFbClient.PostAsync("me/feed", parameters);
 15:             Deployment.Current.Dispatcher.BeginInvoke(() =>
 16:             {
 17:                 IsLoadingMessage = true;
 18:             });
 19:         });
 20:     }
 21: }

 

What we’ve done here is set up our command so that we create the appropriate parameters for a normal boring old Facebook message, set up the acync callback so we actually get something and then, finally, jump over to the UI thread so the IsLoadingMessage property bindings make our UI do what we want.

So all we need to do now is handle the response from our post. We’ll do that with the following callback.

 1: void _asyncFbClient_PostCompleted(object sender, FacebookApiEventArgs e)
 2: {
 3:     if (!e.Cancelled && e.Error == null)
 4:     {
 5:         _asyncFbClient.PostCompleted -= _asyncFbClient_PostCompleted;
 6:         Deployment.Current.Dispatcher.BeginInvoke(() =>
 7:         {
 8:             IsLoadingMessage = false;
 9:             FacebookMessage = "";
 10:         });
 11:     }
 12:     else
 13:     {
 14:         Deployment.Current.Dispatcher.BeginInvoke(() =>
 15:         {
 16:             IsLoadingMessage = false;
 17:         });
 18:     }
 19: }

 

Here we’ve handled the response. If we wanted to be thorough, we’d catch any cancellations or errors in an else and display the results. But in this simple case, it either works and we’re all happy or it doesn’t work and the user is confused because the only indication that it didn’t work is that the FacebookMessage remains unchanged. On the bright side, they can always hit the “send message” button again and give it another try.


Tutorial: Logging Into Facebook with Windows Phone 7 (Silverlight)

4 Comments »

So, you want to use Facebook to sign into something or in some way integrate Facebook with your Windows Phone 7 app. You are in luck because it is almost hilariously easy.

I’ve uploaded this tutorial as a zip file. I tried to github it, but I’m inching up on 1 hour of trying to figure out what the hell I’m doing wrong.

Download this Tutorial Project

I’ve tried to make this a full featured tutorial, so if you just want to get to the code, head down to the “Let the User Login To Facebook” section.

Get Your Facebook Key

Go to http://developers.facebook.com and log in with your Facebook account. Give them the permissions they need and go to the “Apps” tab. Click on “Create new App”

Fill in the App Display Name and the App Namespace and do the verification. Then you’ll get to a page that gives you your App ID and App Secret.

image

Don’t worry about anything else here… you don’t need to select anything in the “how your app integrates with Facebook” section to do this tutorial. If you’re using Facebook integration to do some basic login and simple posting, you could probably just use the Website option.

Also, click the “Graph API Explorer” on the left and keep that open. We’ll come back to that in a moment.

Add Facebook C# SDK

Download the Facebook C# SDK and extract it. Go to the “sl3-wp” folder and unblock the Facebook.dll file (right-click => Properties=>click “Unblock”)

Open up your project (for the example, I used the Visual Studio 10 “Windows Phone Databound Application” template) and right-click on “References => Add References…”. Click “Browse” and navigate to the Facebook.dll and add it to your project.

Build Facebook Login UI

We’ll do this quick here (no MVVM, no bindings) but in later versions I’ll integrate this into a more formal project.

Open your project in Blend. For this quick-and-dirty tutorial, we’ll just add another page title and another panel for the UI we want to show when the user is logged in and set the Visibility to Collapsed on those. Our visual tree should look like this.

image

In our loginPanel, we’re going to add a button and a WebBrowser to our panel. Set the button (containing “sign in using facebook” in the content) to the top and the WebBrowser to fill the panel. For a little flare, I’m going to add “ShowFacebookLogin” and “HideFacebookLogin” animations. My login screen now looks like this (the WebBrowser will animate in when we press the button).

image

When we get our data back, we’re going to tell the user it worked by showing their name and their Facebook avatar. So we’ll add a Grid with an Image and a TextBlock to display the user, along with a friendly “Hello”. (Make sure to name all these things so that we can update them from the code.)

OK… out UI is simple, but ready to roll. Now let’s do something when the user clicks the sign-in button. Go to the “Click” event and add a method like “StartFacebookLogin”.

image

Let the User Login to Facebook

Add “using Facebook;” to your references at the top of your MainPage.xaml.cs file. Now, add the following properties:

private FacebookClient _asyncFbClient;
private string _appID = "get from your facebook app page";
private string _appSecret = "get from your facebook app page";

Now go to your StartFacebookLogin method and add the following (explained at the end).

private void StartFacebookLogin(object sender, RoutedEventArgs e)
{
    string[] extendedPermissions = new[] { "user_about_me", "publish_stream" };

    var oauth = new FacebookOAuthClient { AppId = _appID, AppSecret = _appSecret };
    var parameters = new Dictionary<string, object>
                    {
                        {"response_type", "token"},
                        {"display", "touch"}
                    };
    if (extendedPermissions != null && extendedPermissions.Length > 0)
    {
        var scope = new StringBuilder();
        scope.Append(string.Join(",", extendedPermissions));
        parameters["scope"] = scope.ToString();
    }

    var loginUrl = oauth.GetLoginUrl(parameters);
    webBrowser.Navigated += new EventHandler<NavigationEventArgs>(CheckForAuth);
    webBrowser.Navigate(loginUrl);
}

Remember how I told you to keep the Graph API open? Here is why. It has a big list of all the extendedPermissions that you can tell Facebook you want from the user. Here, we’ve asked for basic user information and the ability to publish to the user’s stream. Ask for only the permissions you need. The user can see the details of your permission request and may reject it if you ask too much.

Next, we create our OAuth client using out AppID and AppSecret and create a Dictionary of parameters communicating to Facebook the details of our request (for example, setting “display”, “touch” tells Facebook that we want the mobile interface.

We write out permission request into our parameters and then get a login url, which we will direct to our webBrowser. Here is what we will should get.

image

At the point Facebook walks the user through their login and, when they are done, it hands us back the access token we’ll need to get the user info and let the user make posts through our app.

This is why we attached the CheckForAuth event handler to our webBrowser. When we navigate to a new page, we’ll check to see if we got an access token using this code:

private void CheckForAuth(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    FacebookOAuthResult result;
    if (FacebookOAuthResult.TryParse(e.Uri, out result))
    {
        if (result.IsSuccess)
        {
            IsolatedStorageSettings Settings = IsolatedStorageSettings.ApplicationSettings;
            if(Settings.Contains("MyFacebookAccessToken"))
                Settings["MyFacebookAccessToken"] = result.AccessToken;
            else
                Settings.Add("MyFacebookAccessToken", result.AccessToken);
            Settings.Save();
            _asyncFbClient = new FacebookClient(result.AccessToken);
            _asyncFbClient.GetCompleted += new EventHandler<FacebookApiEventArgs>(_asyncFbClient_GetCompleted);
            _asyncFbClient.GetAsync("/me");
        }
    }
}

If the Uri does contain a Facebook OAuth result and it is a success, we save the access token to our settings and then immediately use it to get the most basic user information.

The problem we have right now is that we have no class to structure the data that comes back. So get that all squared away.

First, right-click on “References” and select “Add Reference…”. Select “System.Runtime.Serialization”.

Next, add a class to your project (I added mine in a folder called “Models”) and name it FacebookUser.cs.

image

In that class, add the following code

[DataContractAttribute]
public class FacebookUser
{
    public FacebookUser() { }

    private string _id;
    [DataMember(Name = "id")]
    public string ID
    {
        get { return _id; }
        set { _id = value; }
    }

    private string _name;
    [DataMember(Name = "name")]
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

The sample project has a much larger (although still incomplete) version of this model. But this one will do for our purposes.

We’ll make our “GetCompleted” event handler (remember that?) look like this:

void _asyncFbClient_GetCompleted(object sender, FacebookApiEventArgs e)
{
    FacebookUser _fbUser = e.GetResultData<FacebookUser>();

    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        fbName.Text = _fbUser.Name;
        BitmapImage bi = new BitmapImage(new Uri("https://graph.facebook.com/" + _fbUser.ID + "/picture"));
        fbAvatar.Source = bi;
        HideFacebookLogin.Begin();
    });
    _asyncFbClient.GetCompleted -= _asyncFbClient_GetCompleted;
}

What we’ve done here is shove our data into a FacebookUser model. Then we use BeginInvoke to bring ourselves back to the UI thread and set all the properties we want.

Finally, we start the animation that hides the login data and shows that our Facebook login was a success.

Boom!

image


“Operation Not Permitted” On IsolatedStorageSettings in Windows Phone

3 Comments »

This is really fast but it took me a while to figure out. I was getting the following on my recent project when I tried to save something using IsolatedStorageSettings:

“Operation not permitted on IsolatedStorageFileStream.”

And I couldn’t find anything about it other than a very generic “Looks like a threading problem” answers.

Long story short:

I was, in rapid succession, running the same save code twice. What I think happened was that the IsolatedStorageFileStream was still open and trying to save when I tried to get it to save again on another thread.

That’s my guess. I figured I’d toss up this short post on it before I forgot what the problem was.


HttpWebRequest (WebClient) And Tombstoning in Windows Phone 7

6 Comments »

My initial concern here was to deal with tombstoning when it comes to HTTP requests, because that issue has kicked my butt on more than one account. But the second thing you’ll find here is a simple pattern for HTTP requests and responses in Windows Phone 7.

Most of the .NET code I look at uses WebClient to do HTTP requests. But using WebClient can negatively affect the UI thread in Windows Phone 7, so we have to do something a little more like this:

   1:  public void MakeSomeHTTPCall()
   2:  {
   3:      var request = (HttpWebRequest)WebRequest.Create("http://my.awesomewebsite.com");
   4:      request.Method = "GET";
   5:      request.BeginGetResponse(new AsyncCallback(GetSomeResponse), request);
   6:  }

Easy enough, right?

Not so fast!

If the user starts a request and then hits the “power” button on their phone, this will cancel that request. How can we tell when this has happened?

Well, we handle the response to this request in the “GetSomeResponse” method, so let’s take a look at that.

   1:  private void GetSomeResponse(IAsyncResult MyResultAsync)
   2:  {
   3:      HttpWebRequest request = (HttpWebRequest)MyResultAsync.AsyncState;
   4:      try
   5:      {
   6:          HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResultAsync);
   7:          if (response.StatusCode == HttpStatusCode.OK && response.ContentLength > 0)
   8:          {
   9:              using (StreamReader sr = new StreamReader(response.GetResponseStream()))
  10:              {
  11:                  // This result string below is going to be whatever I get back,
  12:                  //   be it JSON or XML or whatever
  13:                  string result = sr.ReadToEnd();                        
  14:              }
  15:          }
  16:      }
  17:      catch (WebException e)
  18:      {
  19:          if (e.Status == WebExceptionStatus.RequestCanceled)
  20:              MessageBox.Show("Looks like your request was interrupted by tombstoning");
  21:          else
  22:          {
  23:              using (HttpWebResponse response = (HttpWebResponse)e.Response)
  24:              {
  25:                  MessageBox.Show("I got an http error of: " + response.StatusCode.ToString());
  26:              }
  27:          }
  28:      }
  29:  }

OK… let’s walk through this.

First, we get our request from the MyResultAsync.AsyncState (line 3), which we’ use to get our response (line 6). Now we can get a HTTP status code (like “200 – OK” or “404 – Not Found”) from this response, right?

No, we cannot. If the response is something other than OK, it will trigger an error and we will jump to the “catch” with a WebException error (line 17).

If we’re coming back from a tombstone (or Fast Application Switching, which will also cancel the request), the WebException status will be “RequestCanceled”. We test for that case and do something special for it (depending on the app, we may want to automatically re-do the request to ensure that we don’t put the user out of sorts by an errant power button press). Otherwise, we know it’s a normal HTTP status code and we can deal with it that way.


Adding Cookies to a Windows Phone 7 HttpWebRequest

2 Comments »

I just spent a couple days on this and, in the end, I didn’t really figure it out. Someone else at my work (the brilliant Rylan Barnes) showed me the workaround for it.

So… you want to add a cookie to your Windows Phone 7 Silverlight HttpWebRequest. Guess what? It sucks to be you! Or, at least, it sucked to be me because I couldn’t find anything on how to do this that worked.

I was working on a project that requires the user to authenticate and, on authentication, sends back a token (unique to that user) to be attached as a cookie for further authentication. However, when I attached the cookie and made my next request, it made that request without the authorization header. Our server said “Hey, looks like you’re not authenticated, I will now forget about that last cookie because you obviously didn’t get it. Have a new one!”

First I’m going to show you things that don’t work.

Didn’t Work: Adding An Empty Cookie Container to the Request

public void DoSomeCRUD(string userName, string pass)
{
    HttpWebRequest request = System.Net.HttpWebRequest.Create("https://myurl.com") as HttpWebRequest;
    if (HasSavedCookieContainer)
        request.CookieContainer = SavedCookieContainer();
    else
        request.CookieContainer = new CookieContainer();
    request.Credentials = new NetworkCredential(userName, pass);
    request.BeginGetResponse(new AsyncCallback(GetMyResponse), request);
}

private void GetMyResponse(IAsyncResult MyResponseAsync)
{
    HttpWebRequest request = (HttpWebRequest)MyResponseAsync.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResponseAsync);
    // this method save the cookie container to IsolatedStorage 
    // so I can attach it to the request the next time I open the app.
    SaveCookieContainer(request.CookieContainer);
}

The saving worked, the cookie container came back just as I saved it. And then… it didn’t work. It was as if the cookie didn’t exist.

Didn’t Work: Ripping The Token Out Of the “Set-Cookie” Header

public void DoSomeCRUD(string userName, string pass)
{
    HttpWebRequest request = System.Net.HttpWebRequest.Create("https://myurl.com") as HttpWebRequest;
    if (IsolatedStorageSettings.ApplicationSettings.Contains["MyToken"])
    {
        string myToken = (string)IsolatedStorageSettings.ApplicationSettings["MyToken"];
        Cookie c = new Cookie("MyCookieName", myToken, "[valid path]", "[valid domain]");
        request.CookieContainer = new CookieContainer();
        request.CookieContainer.Add(new Uri("http://myurl.com"), c);
    }
    else
        request.CookieContainer = new CookieContainer();
    request.Credentials = new NetworkCredential(userName, pass);
    request.BeginGetResponse(new AsyncCallback(GetMyResponse), request);
}

private void GetMyResponse(IAsyncResult MyResponseAsync)
{
    HttpWebRequest request = (HttpWebRequest)MyResponseAsync.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResponseAsync);
    // this method looked for "Set-Cookie" information in the header
    // and the pulls out the token data by brute force and save the
    // token as a string
    if (ResponseHasSetCookieInHeader(response))
    {
        string rawToken = GetTokenFromResponse(response);
        IsolatedStorageSettings.ApplicationSettings["MyToken"] = rawToken;
        IsolatedStorageSettings.ApplicationSettings.Save();
    }
}

The save worked here too, but the same result… it was like the cookie didn’t exist.

This Worked: Adding the Cookie as a Header

Finally we added the token and the credential information as header items. This finally worked.

public void DoSomeCRUD(string userName, string pass)
{
    HttpWebRequest request = System.Net.HttpWebRequest.Create("https://myurl.com") as HttpWebRequest;
    if (IsolatedStorageSettings.ApplicationSettings.Contains["MyToken"])
        request.Headers["Cookie"] = "MyTokenName=" + (string)IsolatedStorageSettings.ApplicationSettings["MyToken"];

    request.Headers["Authentication"] = "Basic " + Convert.ToBase64String(StringToAscii(userName, pass));
    request.BeginGetResponse(new AsyncCallback(GetMyResponse), request);
}

private void GetMyResponse(IAsyncResult MyResponseAsync)
{
    HttpWebRequest request = (HttpWebRequest)MyResponseAsync.AsyncState;
    HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(MyResponseAsync);
    // this method looks for "Set-Cookie" information in the header
    // and the pulls out the token data, saving it to Isolated Storage
    if (ResponseHasSetCookieInHeader(response))
    {
        string rawToken = GetTokenFromResponse(response);
        IsolatedStorageSettings.ApplicationSettings["MyToken"] = rawToken;
        IsolatedStorageSettings.ApplicationSettings.Save();
    }
}

For the sake of giving credit, here is the StringToAscii method for the Authentication, tweaked from this StackOverflow answer from Hans Passant

public static byte[] StringToAscii(string userName, string pass)
{
    string s = userName + ":" + pass;
    byte[] retval = new byte[s.Length];
    for (int ix = 0; ix < s.Length; ++ix)
    {
        char ch = s[ix];
        if (ch <= 0x7f) retval[ix] = (byte)ch;
        else retval[ix] = (byte)'?';
    }
    return retval;
}

Finding the Unique Device ID in Windows Phone 7 (And Device Manufacturer And Anonymous Windows Live ID)

2 Comments »

I’m tired of trying to find things about Windows Phone 7 development, so I’m just going to post links that I find helpful so I can find them later.

Here’s Nick Harris with a handy set of static methods for getting the following unique IDs:

  • Device Manufacturer ID
    • DeviceExtendedProperties.TryGetValue(“DeviceManufacturer”, out someObject);
    • example: “HTC”
  • Device ID
    • DeviceExtendedProperties.TryGetValue(“DeviceUniqueId”, out someObject);
    • requires ID_CAP_IDENTITY_DEVICE in the app manifest which will trigger a warning to users when they install the app
    • a byte[], converter to a string will looks like
      “12345678901234567890123456789012345678901234567890123”
  • Anonymous Windows Live ID
    • A 32 character subset at offset 2  of the results of
      “UserExtendedProperties.TryGetValue(“ANID”, out someObject)
    • requires ID_CAP_IDENTITY_USER in the app manifest which will trigger a warning to users when they install the app
    • looks like “00FF00FF00FF00FF00FF00FF00FF00FF”

However, if you just need any unique identifier (not necessarily a device ID), you can always set and store a new global unique identifier using:

Guid.NewGuid();

which will return a 128-bit integer that will look something like this:

“e81644f1-46b6-4994-2903-1d1f1440c130″

This will not cause warnings to appear when the app is downloaded because it isn’t a constant identifier to that specific device.


Windows Phone 7 Push Notification For Beginners–The Device

2 Comments »

OK… it’s been almost 2 months since I tried to start this series and now I’m going to finish it. A brief warning: this is done with pre-Mango bits so it won’t have all the latest, greatest most exciting things like the back-tile functionality or deep linking. (Here’s a good blog post on all that.) But it remains a good introduction.

Windows Phone 7 Push Notification Project Files (github)

The goal of this post is to provide a sample Push Notification application that is

  • easy to test
  • good architecture
  • provides a sample web app for testing your push code (part of the delay has been because I’ve been trying to be a perfectionist on that web app. I’ve decided I’m never going to get around to making it perfect so this is the best I can do with the time I have)

Too many of the sample apps I’ve seen shove the push notification code in the xaml code-behind, leaving it to us to separate out the bits and translate it into a real project. This project uses MVVMLight binding and an event-driven architecture to get the push stuff working.

So… let’s dig into it.

I created a class called PushNotificationService that held a number of helpful little variables and objects. The most important variable here is

private static string _pushChannelName = "SampleAppNotification";

This name will delineate our push service from other services. If something weird happens and your push service stops working, the first thing you should do is change this string.

Next, we have a method that allows us to control when we get the push notification Uri. As an overview of what we’re doing,

  1. See if we already have a valid HttpNotificationChannel (the object that will control the push permissions and handle information from the Microsoft Push server)
  2. If we do have a valid HttpNotificationChannel, make sure we got the channel Uri correctly (the uri we will send out push notifications to). If we did, SUCCESS! Otherwise, go to step 3.
  3. Set the event handlers so we can handle when we get a new channel Uri back from the Microsoft Push server.
  4. Ask the Microsoft Push server for a new channel Uri.
  5. Set the HttpNotificationChannel up to handle the right kind of push notifications.
  6. Handle the returned uri from the Microsoft Push server & send it to the rest of the app.

Step 1

_notificationChannel = HttpNotificationChannel.Find(_pushChannelName);

Step 2

if (_notificationChannel.ChannelUri != null)
{
      // Success! We run the event to send that info back to our ViewModel 
      RaiseGotPushUri(_notificationChannel.ChannelUri);
}

Step 3

else
{
    _notificationChannel = new HttpNotificationChannel(_pushChannelName);
    _notificationChannel.ChannelUriUpdated +=
         new EventHandler<NotificationChannelUriEventArgs>(_notificationChannel_ChannelUriUpdated);
    _notificationChannel.HttpNotificationReceived +=
         new EventHandler<HttpNotificationEventArgs>(_notificationChannel_HttpNotificationReceived);
    _notificationChannel.ErrorOccurred +=
         new EventHandler<NotificationChannelErrorEventArgs>(_notificationChannel_ErrorOccurred);
}

Step 4

_notificationChannel.Open();

Step 5

BindNotifications(_notificationChannel);

Binding Details

In the pre-Mango push notifications, there are 3 kinds of push notifications and we have to announce what kind of notifications we plan on handling.
First, there are toast notifications, which look like this (stolen from Shawn Wildermuth):
image

Toast notifications consist of

  • a title (“Toast Message” in the example above)
  • a message (“This is from the server”)

To bind them, we simply type:

_thisChannel.BindToShellToast();

Tile notifications will only show up if the user has pinned the application to the front application tile board on the phone. I like to split Tile notifications into two types because we have to handle them differently in the code.

The first kind of tile notification is what I call “simple” Tile notifications. With simple Tile notifications, we can change a number and title on our app tile. The new title will show up where the title always shows up (at the bottom left) and the number will show up in a black circle at the top right.

image

Doing this much is simple:

_thisChannel.BindToShellTile();

But then there are Live Tiles, which allow us to send a whole new image to the tile to change it in a more holistic way to represent some push data. (We can still update numbers and titles too.) Live Tiles, however, require that we whitelist all the websites that might want to send an image to our phone. So we need to create a collection of whitelisted domains and add that to our tile binding.

System.Collections.ObjectModel.Collection<Uri> permittedImageHosts = new System.Collections.ObjectModel.Collection<Uri>();
permittedImageHosts.Add(new Uri("http://www.designersilverlight.com"));
_thisChannel.BindToShellTile(permittedImageHosts);

If you’re going to use my handy-dandy WP7 Push Tester, make sure you whitelist the exact domain above.

And that’s it… that’s all we need to do to get everything bound and ready to go! All we need now is to get the Uri from the Microsoft Push server so we know where to send our Push Notifications to.

Step 6

void _notificationChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
      RaiseGotPushUri(e.ChannelUri);
}

This will run when we get the updated Uri back and we just send it in our event, which the ViewModel is listening to.

I’ve really streamlined the code in this blog post to deal with just the bare essentials. If you want to look at the project in detail, you can download it here.

Now, all we have to do is start testing it.

You can test it using my WP7 Push Notification web app. I’m also working on another post that walks through creating a push notification system using PHP, but in the meantime you might want to check out this PHP library that I used.


Windows Phone 7 Push Notifications For Beginners (Now With Testing!)

3 Comments »

I know there are about a thousand blog posts on implementing push notifications in a Windows Phone 7 application. But having now implemented push notifications a couple times into WP7 projects, I felt like something was missing from the community knowledge base. So, in order to try to cover WP7 Push notifications for the uninitiated, I’m putting together a set of posts will try to cover the following topics:

  1. Windows Phone 7 Push Notifications (10,000 Foot View)
  2. Implementing Push Notifications on a Device (with Project code)
  3. Testing Push Notifications On My Device Without Writing a Goddamn Web Service (Also, How To Write A WP7 Push Service in PHP)

Windows Phone 7 Push Notifications (10,000 Foot View)

The Windows Phone 7 push notification is actually an extremely elegant way of doing push notifications. Personally, I love it. I’ll walk through the steps conceptually here and then mirror the steps in the code post.

(Note to experts: I may be getting some of the details about how this works in the underlying architecture wrong. However, this is how it seems to me that it works and it makes sense this way.)

Step 1: Say “Hey, phone! I want to send you push notifications about some stuff.” When you do this, you’re doing it with a couple of conditions. The first is that you’re giving your specific push service a name (like “Bob” but hopefully a little more specific).

Next, you’ll need to determine if you want to use the “Toast” notification or the “Tile” notification or the “Raw” notification or some combination of these three. When you know what kind of notifications you want, you’ll basically write a magic piece of code which communicates to the magical push notification fairy, who, in return for your good deeds, gives you a device/application specific URL that you will use to send notifications to your phone.

image

You think I’m kidding. I’m not. As a preview, the code you need to write is: “myPushStuff.Open()”. And that’s it. Then you just wait for the magical push notification fairy to give you the URL you’ll use to send notifications to your phone.

You don’t actually need to send information about toast and tile to the push registration service. However, if you decide later on thatyou actually wanted to send a toast notifications, not a tile notification, your old URL won’t work… you’ll need to save a new one. Don’t know why or how exactly this happens… just passing along helpful information.

If you’re looking for information about the difference between tile, toast and raw notifications, the image below was stolen from the msdn article that talks about the differences. Go read about it there… I won’t stoop to copying and pasting all their excellent information into my blog post.

AP_Con_Notifications_ToastTile

Step 2: Once you have your magical URL, save it in such a way that whatever webservice you’re using can recognize which phone it’s tied to. Maybe you’re saving it along with a username or with a zip code (like with a weather service). In any case, you’ll want to be able to send the right push notifications to the right phones.

When the time comes to send the notification, your webservice will need to send an XML chunk created for your notification (see details here) to the phone-specific URL. Then, the Microsoft Push Notification Service handles your push request and forwards it to the phone, sending a response telling you that it worked (or didn’t work).

image

I’ve got my gripes with Windows Phone 7, but the push notification implementation ain’t one of them. It’s very straightforward and can be implemented on the phone with very little code and on a server with similar ease. If you’re a newbie mobile developer and this looks complicated, go try to implement push notification on Android or iOS. For all you Android and iOS people out there I would like to say:

Ha.

The next post will walk through the steps to register your app for push notifications. I’ll post a link to it in this post when I get it up.


How To Load MIX Outsider (With Or Without a Phone)

No Comments »

The very latest and greatest version of the MIX Outsider application is up and ready for download. Mostly text-building fixes and settings updates.

Also, check out the MIX Outsider website, built with loving care by Jason Alderman (Twitter: @justsomeguy)

If you download the app above, you’ll notice it is in the *.xap format, which is the format for all Silverlight based Windows Phone 7 mobile apps. Perhaps you’ve never side-loaded a WP7 app before or perhaps you don’t have a Windows Phone 7 device. Fear not! If you have the Windows Phone 7 developer tools, you can load the app to your emulator and just run it from there.

The following 90 second video show you how. It really is so easy that it takes less than 90 seconds.

Sideloading the MIX11 Outsider App To The Emulator from Matthias Shapiro on Vimeo.

Have fun and I’ll see you at MIX11!


Follow me: matthiasshapiro