Programmatically Updating SharePoint User Profiles with Facebook Data

While giving my demo at SharePoint Saturday Boston last weekend, I showed how to populate a Contacts list in SharePoint with data from the currently logged in user’s Facebook profile. An audience member posed a question about user profiles in SharePoint and how data from Facebook could also be used to populate them. Though I had never considered the potential applications of doing this (one might not think to leverage SharePoint user profiles in a public-facing scenario), it is technically straightforward to do.

Prerequisites

In order to surface Facebook profile information in a SharePoint user profile, you should have the following in place:

  • A My Site Host site collection deployed on the same web application where Facebook is configured as an identity provider.
  • User Profile properties configured to allow the user to edit values for the properties you wish to set/update programmatically.

Objective

In our scenario, we will take the following information from a user’s Facebook profile and use it to populate his/her SharePoint user profile:

  • Given name
  • Job title
  • Location
  • “About me” bio
  • Birthday
  • Profile picture

Our Starting Point

Upon initially configuring Facebook as an identity provider for SharePoint, a very bare bones user profile will appear when selecting “My Profile” from the welcome menu.

The profile page (person.aspx) shows the claims-encoded name for the user, and that’s about it:

The Code

The algorithm required to update a user profile for a user logged in via Facebook is the same as it is for any other SPUser; however, we will utilize the Facebook C# SDK to encapsulate calls to the Facebook Graph API to get the information we need. For demonstration purposes, I have this code wired up to a button click event handler in a SharePoint web part.

This code leverages JSON.NET to parse the JSON-formatted values returned by calls to the Facebook Graph API.

// Iterate through the Claims we are presented until we find the Facebook AccessToken
// and given name
IClaimsPrincipal claimsPrincipal = Page.User as IClaimsPrincipal;
claimsIdentity = (IClaimsIdentity)claimsPrincipal.Identity;
foreach (Claim c in claimsIdentity.Claims)
{
    if (c.ClaimType.Equals("http://www.facebook.com/claims/AccessToken"))
    {
        // We will use this Claim to make all calls to the Facebook Graph API
        token = c.Value;
    }
    else if (c.ClaimType.Equals("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"))
    {
        // We will use this Claim to set the proper display name for the user
        givenName = c.Value;
    }
}

// Assuming we have the AccessToken, use it to access the user's Facebook profile
if (!string.IsNullOrEmpty(token))
{
    var client = new Facebook.FacebookClient(token);
    var me = (IDictionary)client.Get("me");

    Guid siteId = SPContext.Current.Site.ID;
    Guid webId = SPContext.Current.Web.ID;

    // Assume the identity of the application pool - this account is configured as an
    // Administrator of my User Profile Service Application in Central Administration
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (SPSite site = new SPSite(siteId))
        {
            try
            {
                // Obtain a reference to the UserProfileManager for this SPSite
                SPServiceContext sc = SPServiceContext.GetContext(site);
                UserProfileManager userProfileMangager = new UserProfileManager(sc);

                SPUser currentUser = SPContext.Current.Web.CurrentUser;
                if (currentUser != null)
                {
                    // Get the current user's SharePoint profile
                    UserProfile profile = userProfileMangager.GetUserProfile(true);

                    // Update the display name and preferred name to match given name
                    profile.DisplayName = givenName;
                    profile[PropertyConstants.PreferredName].Value = givenName;
                    profile[PropertyConstants.Birthday].Value = (string)me["birthday"];
                    profile[PropertyConstants.AboutMe].Value = (string)me["bio"];
                                    
                    // Get the current job title
                    JsonArray work = me["work"] as JsonArray;
                    // Most recent/current employer stored in work[0]
                    JsonObject company = work[0] as JsonObject;
                    if (company.ContainsKey("position"))
                    {
                        JsonObject position = company["position"] as JsonObject;
                        profile[PropertyConstants.JobTitle].Value = (string)position["name"];
                        profile[PropertyConstants.Title].Value = (string)position["name"];
                    }
                                    
                    // Get the current location
                    JsonObject location = me["location"] as JsonObject;
                    string cityState = (string)location["name"];
                    profile[PropertyConstants.Location].Value = cityState;

                    // Get the user's current Facebook profile picture
                    // https://graph.facebook.com/[Facebook Profile ID]/picture?type=large
                    profile[PropertyConstants.PictureUrl].Value = "https://graph.facebook.com/" + (string)me["id"] + "/picture?type=large";
                                    
                    // Commit all changes to the user's profile
                    profile.Commit();
                }

                lblOutput.Text = "User profile successfully updated.";
            }
            catch (Exception ex)
            {
                lblOutput.Text = "" + ex.Message + "
" + ex.StackTrace + "
"; } } }); }

The Outcome

After executing this code, the user’s SharePoint profile looks a lot more complete!

One Final Thing

My demos include a basic “status update” web part that allows a user to type a status message in a SharePoint web part. With a few additional lines of code, we can update the “What’s happening?” text bubble to include the text of this status update as well:

SPServiceContext sc = SPServiceContext.GetContext(site);
UserProfileManager userProfileMangager = new UserProfileManager(sc);
UserProfile profile = userProfileMangager.GetUserProfile(true);
profile[PropertyConstants.StatusNotes].Value = txtStatus.Text;
profile.Commit();

Now whenever I post a status update, it will update both my Facebook profile and my SharePoint profile!