Cutting Edge

Essential Facebook Programming: Building a Windows Client

Dino Esposito

Download the Code Sample ( VB Version)

Dino EspositoIn my previous column I discussed the basics of Facebook programming in the context of a Web site—specifically an ASP.NET MVC Web site (you can read the article at msdn.microsoft.com/magazine/jj863128). As you can imagine, the use of the Facebook API isn’t limited to Web apps, even though one of its most common uses is just to authenticate users of a new Web site in a “softer” manner.

In this column I’ll build a Windows Presentation Foundation (WPF) client app that uses the Facebook API to authenticate users and post updates with pictures. Because the Web is a different environment from the desktop, this column obviously will be different from what I wrote last month. The Facebook API, however, is the same. You can get the Facebook C# SDK via NuGet (see facebookapi.codeplex.com for more details on the Facebook API for C#/.NET developers).

Integrating Apps with Social Networks

Most social networks have a similar architecture. Interaction between users and the engine of the social network happens in either of the following two ways: directly via the main Web site (for example, the Twitter or Facebook site) or through the mediation of an app hosted internally by the social network site. For the sake of clarity, I’ll refer to these apps as connectors.

A client app (Web site, WPF or Windows Phone) can only interact with the engine of the social network through the mediation of a connector. For the sample code accompanying this column, I’ll use a Facebook connector called Memento (note that the code, provided for example purposes, comes as a single project, not a full solution, and uses Visual Studio 2010). The name Memento—and its related icon—will show up as the footer of any wall posts made by any client app using Memento to connect to Facebook. You can create a connector for Facebook at developers.facebook.com/apps.

Connectors are characterized by a pair of unique strings—app key and secret—and, more interestingly for our purposes, can serve a variety of client apps, whether Web, mobile or desktop. Figure 1 summarizes the overall architecture of social networks when it comes to interaction.

The Interaction Model of Social Networks
Figure 1 The Interaction Model of Social Networks

In the end, any user apps that need to integrate with most popular social networks (for example, Facebook, Twitter or Foursquare) are essentially built as clients of a social network-specific connector app.

For an app, integrating with a social network essentially means accessing the social network functionalities on behalf of a registered user. This involves a couple actions: authenticating users against the social network and performing the actual action, such as making a check-in for a given venue, posting on the user’s wall or tweeting.

This is the essence of integrating a social network API into a custom app and, as it turns out, it might not be limited to just Web apps.

Differences from a Windows App

In last month’s column I first discussed how to authenticate users of a Web site via Facebook, then I presented some code to post both interactively and programmatically to the user’s wall. Posting to a user’s wall doesn’t require a different approach if done from a Windows app; authentication, instead, requires some adjustments.

A social network is primarily a Web app and exposes authentication services via the OAuth protocol. An app that wants to authenticate its users via Facebook accounts, for example, needs to place an HTTP call to some Facebook endpoint. The endpoint, however, returns an HTML page for the actual user to interact with by entering credentials and authorizing the connector to operate on her behalf (see Figure 2).

The Memento Connector Explicitly Asks the User for Permissions
Figure 2 The Memento Connector Explicitly Asks the User for Permissions

The part that’s different in a Windows or mobile scenario compared to a Web app is how you handle the redirect to the HTML page that the social network provides for credentials and permissions.

Yet Another Facebook Windows Client

Let’s create a WPF project and add a bit of XAML markup to the main window. At the minimum, you need to have a couple of buttons to trigger the login and logout process, and a label to display the name of the currently logged-in user. In addition, you can have an image element to display the picture of the current user. What else? Let’s look at the code you put in the Login click handler:

var loginUrl = FbHelpers.GetLoginUrl();

The first step is getting the login URL from Facebook. The code to get the URL is the same as you’d use in a Web scenario, as shown in Figure 3.

Figure 3 Code to Get Login URL

public static String GetLoginUrl()
{
  var client = new FacebookClient();
  var fbLoginUri = client.GetLoginUrl(new
  {
    client_id = ConfigurationManager.AppSettings["fb_key"],
    redirect_uri =
    "https://www.facebook.com/connect/login_success.html", 
    response_type = "code",
    display = "popup",
    scope = "email,publish_stream"
  });
  return fbLoginUri.ToString();     
}

As you might notice, the redirect_uri parameter (required) points to a Facebook success endpoint. That’s the landing page for after the login process has terminated. In a Web scenario you’d use the current page, so the user is first redirected to the Facebook site and then back to the original requesting page.

The GetLoginUrl method only gets you the URL to call to log in. In a Web scenario, you simply invoke a redirect to switch to the new page and display the typical Facebook UI for login or—if the user is already logged in on the computer in use—the permission page as shown in Figure 2. To achieve the same in a Windows app, you need an initially hidden WebBrowser control in the UI. Here’s the full code for the click handler of the app’s login button:

public void Login()
{
  var loginUrl = FbHelpers.GetLoginUrl();
  ShowBrowser = true;
  view.Browser.Navigate(loginUrl);
}

The sample app available for download uses the Model-View-ViewModel (MVVM) pattern to abstract away UI details. Therefore, setting ShowBrowser to true just has the effect of turning on the visibility of the WebBrowser control. Finally, the Navigate method directs the component to the specified URL. Figure 4 shows the status of the sample app before and after the login click.

First Step of Login to Facebook
Figure 4 First Step of Login to Facebook

The authentication process might take up to two steps. If the user is already logged in to the social network, the Web browser directly receives the landing page. If the user is not logged in, the page shown in Figure 4 is presented. However, if the user isn’t associated with the connector being used by the client app, then an intermediate screen like that shown in Figure 2 explicitly asks to grant permissions.

How do you handle the load of pages in the WebBrowser component? You basically need a Navigated event handler:

void facebookBrowser_Navigated(Object sender, 
  NavigationEventArgs e)
{
  var fb = new FacebookClient();
  FacebookOAuthResult oauthResult;
  if (!fb.TryParseOAuthCallbackUrl(e.Uri, out oauthResult))
    return;
  if (oauthResult.IsSuccess)           
    _viewPresenter.LoginSucceeded(oauthResult);           
  else           
    _viewPresenter.LoginFailed(oauthResult);
}

Facebook indicates whether the login process completed successfully or not. Note that the login fails if the user simply denies requested permissions to the connector. If the login fails, just reset the UI hiding the Web browser and display some feedback to the user. It’s much more interesting when the login is successful, as shown in Figure 5.

Figure 5 Upon a Successful Login

public void LoginSucceeded(FacebookOAuthResult oauthResult)
{
  // Hide the Web browser
  ShowBrowser = false;
  // Grab the access token (necessary for further operations)
  var token = FbHelpers.GetAccessToken(oauthResult);
  Token = token;
  // Grab user information
  dynamic user = FbHelpers.GetUser(token);
  // Update the user interface
  UserName = String.Format("{0} {1}", user.first_name,
    user.last_name);
  UserPicture = user.picture;
  IsLogged = true;
}

The code in Figure 5 is similar to what you need to use in a Web scenario. Note that once the user has logged in successfully, the app is still not yet ready to operate on behalf of the user. Moreover, the app doesn’t yet know anything about the user—not even the user’s name or some sort of ID. This means that persisting authentication data isn’t possible yet. Therefore, another step is mandatory for both Web and Windows scenarios: getting the access token.

The Access Token

The access token is a string you get from the social network in return for a successful login code. The login code simply indicates that the user who proceeded with authentication is known to the network. The access code ties together the user identity and the connector. The access code tells the social network engine whether the user app has enough permission to perform the requested operation on behalf of that user. The same user has a different access token for different connectors.

Figure 6 shows the C# code to get the access token after a successful OAuth login.

Figure 6 Code to Get Access Token After Successful OAuth Login

public static String GetAccessToken(FacebookOAuthResult oauthResult)
{
  var client = new FacebookClient();
  dynamic result = client.Get("/oauth/access_token",
    new
    {
      client_id = ConfigurationManager.AppSettings["fb_key"],
      client_secret =
      ConfigurationManager.AppSettings["fb_secret"],
      redirect_uri =
      "https://www.facebook.../login_success.html", 
      code = oauthResult.Code
  });
  return result.access_token;
}

In a Web app, you might want to persist the access token in a custom cookie or as extra data in a custom authentication cookie managed by a custom IPrincipal object. In a Windows scenario, you might want to resort to local storage. When the user logs out of a Windows app, you simply clear out any stored data. Once you hold the access token for a given user and connector, you’re ready to perform any operation that falls under the granted permissions, as shown in Figure 2.

A common type of social network app “listens” to some feed and posts automatically on behalf of the same user. In this case, you grab the access token once and keep on running the app until the user revokes permissions. Once you hold the access token, you don’t need to deal with authentication as long as the user behind the token is actually logged in to the social network on the computer.

Posting Status and Photos

Figure 7 shows the UI of the sample WPF app once the user is successfully logged in to Facebook and the access token is safely stored. The UI includes a text box and a button to post. As you can see, the UI also defines a button to browse and selects a JPEG image from the local disk.

Posting from the Sample Client App
Figure 7 Posting from the Sample Client App

The code in Figure 8 shows how to post an update with an attached picture.

Figure 8 Code to Post an Update with an Attached Picture

public static void PostWithPhoto(
  String token, String status, String photoPath)
{
  var client = new FacebookClient(token);
  using (var stream = File.OpenRead(photoPath))
  {
    client.Post("me/photos",
    new
    {
      message = status,
       file = new FacebookMediaStream
  {
         ContentType = "image/jpg",
         FileName = Path.GetFileName(photoPath)
        }.SetValue(stream)
    });
  }
}

In Figure 7 you see the update and picture posted to my timeline. Note that the name of the connector used is presented under the name of the author.

Next Up: JavaScript

In this article I built a WPF app to post to Facebook on behalf of a user. To build a mobile app, you follow the same pattern discussed here. Note that the pattern is valid regardless of the mobile platform of choice. I’ve successfully built Windows Phone and Android apps in this same way. My next column will show how to use JavaScript to program Facebook.


Dino Esposito is the author of “Architecting Mobile Solutions for the Enterprise” (Microsoft Press, 2012) and “Programming ASP.NET MVC 3” (Microsoft Press, 2011), and coauthor of “Microsoft .NET: Architecting Applications for the Enterprise” (Microsoft Press, 2008). Based in Italy, Esposito is a frequent speaker at industry events worldwide. Follow him on Twitter at twitter.com/despos.

Thanks to the following technical expert for reviewing this article: Scott Densmore

 

Rate: