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!