Zend certified PHP/Magento developer

BuildMobile: Facebook in a Windows Phone 7 App

In the previous post “Using Windows Live ID in a Windows Phone Application” you saw how you can authenticate a user and retrieve their profile from Windows Live. Facebook also uses OAuth 2 to allow third party applications to authenticate and interact with Facebook data. In this post you’ll learn about Facebook’s implementation and how you can post status updates back to Facebook from within your Windows Phone application.

Step 1: Creating a Facebook Application

Open a web browser and go to the Facebook Developer Page. In order to create an application you’ll need to sign in with a set of Facebook credentials. Again, we recommend creating a dedicated Facebook account for managing your applications.

Click on the Apps tab, followed by the Create New App button. You’ll be prompted to enter information about the application you’re creating (Figure 1). Remember that most of this information will be seen by the user when they’re authorizing your application to access their Facebook account.

Facebook WP7 Figure 1

Figure 1

Once you click the “Continue” button you’ll be prompted to complete a captcha-style challenge, before being allocated a App ID and App Secret (Figure 2).

Facebook WP7 Figure 2

Figure 2

Step 2: Creating the Shell Windows Phone App

To illustrate the process of authenticating against Facebook we’ll use a similar application to the one we used previously to authenticate with Windows Live ID. Again we have a WebBrowser control, a Button to trigger the authentication process and two TextBlock controls to display user information.

phone:PhoneApplicationPage x:Class="FacebookSampleApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    Grid
        StackPanel x:Name="LayoutRoot" Background="Transparent"
            Button Content="Authenticate" Click="AuthenticateClick" /
            TextBlock x:Name="UserNameText" /
            TextBlock x:Name="UserIdText" /
        /StackPanel
        phone:WebBrowser x:Name="AuthenticationBrowser" Visibility="Collapsed"
                                                Navigated="BrowserNavigated" IsScriptEnabled="True" /
    /Grid
/phone:PhoneApplicationPage

Step 3: Create the Login URL

This step involves building the correct URL to navigate the WebBrowser control to so that the user can sign into Facebook. The URL consists of a number of elements:

  • The Base url: http://www.facebook.com/dialog/oauth
  • Query String Parameters:
    • Client ID: The App ID allocated to the Facebook application you just created
    • Response Type: The type of authentication to use (we’re going to use “token”)
    • Scope: The parts of the users account the host application is requesting access to
    • Redirect URL: The URL that the browser will redirect to after authentication has been completed. In this case we’ll use the rich client return URL hosted by Facebook, http://www.facebook.com/connect/login_success.html.
    • Display: Determines how the login prompt will be styled. Use “touch” in order to get the most usable interface for a touch driven device.

The only trick to this step is making sure that all the parameters are correctly concatenated and appropriately URL encoded.

var uriParams = new Dictionarystring, string() {
                        {"client_id", "your_app_id"},
                        {"response_type", "token"},
                        {"scope", "user_about_me, offline_access, publish_stream"},
                        {"redirect_uri", "http://www.facebook.com/connect/login_success.html"},
                        {"display", "touch"}
                    };
StringBuilder urlBuilder = new StringBuilder();
foreach (var current in uriParams) {
    if (urlBuilder.Length0) {
        urlBuilder.Append("");
    }
            var encoded = HttpUtility.UrlEncode(current.Value);
            urlBuilder.AppendFormat("{0}={1}", current.Key, encoded);
}
var loginUrl= "http://www.facebook.com/dialog/oauth?" + urlBuilder.ToString();

The scope elements defined here request permission for the application to access profile information (“user_about_me”), persist the access tokent (“offline_access”) and publish status updates (“publish_stream”).

Step 4: Prompt the User to Login

To get the user to login, all you have to do is to navigate the WebBrowser control to the loginUrl you just created. In the case of the application you’ll also need to display the WebBrowser control.

AuthenticationBrowser.Navigate(new Uri(loginUrl));
AuthenticationBrowser.Visibility = Visibility.Visible;

Step 5: User Logs In and Approves the Application

The user will see a number of screens which will prompt them to enter their credentials and then grant the requested permissions to the application (Figure 3).

Facebook WP7 Figure 3

Figure 3

Step 6: Extract the Access Token

In Figure 3, the final image is the redirect URI where your application should parse the URI query string for this page and extract the access token, before hiding the WebBrowser control.

public string AccessToken { get; set; }
private void BrowserNavigated(object sender, NavigationEventArgs e) {
    if (string.IsNullOrEmpty(e.Uri.Fragment)) return;
    if (e.Uri.AbsoluteUri.Replace(e.Uri.Fragment,"")==
         "http://www.facebook.com/connect/login_success.html") {
        string text = HttpUtility.HtmlDecode(e.Uri.Fragment).TrimStart('#');
        var pairs = text.Split('');
        foreach (var pair in pairs) {
            var kvp = pair.Split('=');
            if (kvp.Length == 2) {
                if (kvp[0] == "access_token") {
                    AccessToken = kvp[1];
                    MessageBox.Show("Access granted");
                }
            }
        }
        if (string.IsNullOrEmpty(AccessToken)) {
            MessageBox.Show("Unable to authenticate");
        }
        AuthenticationBrowser.Visibility = System.Windows.Visibility.Collapsed;
    }
}

Step 7: Accessing Content from Facebook

The Access Token that you’ve received should only be used to interact with Facebook and should not be used to uniquely identify the current user. To access user information, including a unique identifier, you should request their profile information via the Facebook graph API. Graph API requests start with the base URL of https://graph.facebook.com to which you append a path that reflects the data you are requesting. In the case of profile information you simply need to append /me to the base url. The following code illustrates making a HttpWebRequest to retrieve profile information from Facebook.

private void RequestUserProfile() {
    var profileUrl = string.Format("https://graph.facebook.com/me?access_token={0}",
                                                           HttpUtility.UrlEncode(AccessToken));
    var request = HttpWebRequest.Create(new Uri(profileUrl));
    request.Method = "GET";
    request.BeginGetResponse(result = {
              try {
                  var resp = (result.AsyncState as HttpWebRequest).EndGetResponse(result);
                  using (var strm = resp.GetResponseStream()) {
                      var serializer = new DataContractJsonSerializer(typeof (FacebookProfile));
                      var profile = serializer.ReadObject(strm) as FacebookProfile;
                      this.Dispatcher.BeginInvoke(
                          (ActionFacebookProfile) ((user) = {
                                                      this.UserIdText.Text = user.Id;
                                                      this.UserNameText.Text = user.Name;
                                                                                                    }), profile);
                                            }
              }
              catch (Exception ex) {
                  this.Dispatcher.BeginInvoke( () =
                      MessageBox.Show("Unable to attain profile information"));
              }
          }, request);
}
[DataContract]
public class FacebookProfile {
    [DataMember(Name="id")]
    public string Id { get; set; }
    [DataMember(Name="name")]
    public string Name { get; set; }
}

The final output is the user’s name and ID appearing in the relevant TextBlock controls (Figure 4).

Facebook WP7 Figure 4

Figure 4

Step 8: Posting a Status Update

To request profile information you performed a GET operation against the profile path /me. In order to update the user’s status you need to POST to the status feed at /me/feed. In contrast to the GET operation, where the Access Token was passed as a URL parameter, with the POST operation all arguments are specified as form parameters in the body of the request. The following code illustrates posting a status update using a HttpWebRequest.

private void PostStatusUpdate(string status, Actionbool, Exception callback) {
    var request = HttpWebRequest.Create("https://graph.facebook.com/me/feed");
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.BeginGetRequestStream((reqResult) = {
        using (var strm = request.EndGetRequestStream(reqResult))
        using (var writer = new StreamWriter(strm)) {
            writer.Write("access_token=" + AccessToken);
            writer.Write("message=" + HttpUtility.UrlEncode(status));
        }
        request.BeginGetResponse((result) = {
            try {
                var response = request.EndGetResponse(result);
                using (var rstrm = response.GetResponseStream()) {
                    var serializer = new DataContractJsonSerializer(typeof(FacebookPostResponse));
                    var postResponse = serializer.ReadObject(rstrm) as FacebookPostResponse;
                    callback(true, null);
                }
            }
            catch (Exception ex) {
                callback(false, ex);
            }
        }, null);
    }, null);
}
[DataContract]
public class FacebookPostResponse {
    [DataMember(Name = "id")]
    public string Id { get; set; }
}

In order to allow the user to specify their new status, let’s add a TextBox and a Button to the user interface:

TextBox x:Name="StatusText" /
Button Content="Post Status Update" Click="PostUpdateClick" /

The PostUpdateClick method will in turn call the PostStatusUpdate method, passing in the value of the TextBox.

private void PostUpdateClick(object sender, RoutedEventArgs e) {
    PostStatusUpdate(this.StatusText.Text, (success,ex)= {
        this.Dispatcher.BeginInvoke(() = {
            if (success  ex == null) {
                MessageBox.Show("Status updated");
            }
            else {
                MessageBox.Show("Unable to update status");
            }
        });
    });
}

In this post you’ve seen how to authenticate against Facebook and to interact with the Facebook Graph API to retrieve and update data. Facebook contains a wealth of data about the user, their friends and their social activities, most of which is accessible via the Graph API. However, a word of caution: Facebook, like other social networks, has a habit of updating their APIs and occasionally the policies for using their APIs. Make sure you develop your application to be resilient to changes and gracefully handle any exceptions that may result from changing APIs. More information is available via the Facebook Developer Portal and the Facebook Graph API documentation.