Monday, 13 February 2012

Retrieving MySite Info to a list via a User Value Field

Greetings. I have not updated this blog from some time because I was on leave all of January and was relaxing and enjoying myself. I follow SharePoint on my twitter feed and one of the tweets was "Do you dream about #SharePoint?" and I RT'ed the tweet with the additional comment, "You've got to be joking!" But now I am back and thoughts of such things return to my mind. This will be my first post for 2012, then. I spent quite some time struggling with this one. As far as I know it's the one place where the whole routine is present in one place so if anyone needs it they can use it.

If you want to get more info on a user, often you'll click on their MySite. This code effectively does the same thing. If you have a list or library that contains a "user or group" control, you can retrieve the user information from the field and you can use the UserProfileManager object to get all the info on that user. To do this, you're going to need some libraries that you might not normally have in your .NET store. So, first:

using System;
using Microsoft.SharePoint;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
using System.Web;

Now, if you can't see the Microsoft.Office.Server library in your usual reference store, don't panic. Go to your Twelve Hive folder and look for the ISAPI directory. The dll file should be in there. Add it in as a reference to your VB project.

Let's presume you are going to create a conventional event handler for the ItemAdded event and copy the resulting data into a text field called "Business Unit". We'll skip the event handler code as we've covered that already. I'm now going to use a privilege wrapper and get the string value of the user field. This was the bit that caused me by far the most grief. The ToString() method would not work on the user control field. Don't ask me why it wouldn't work, it just wouldn't. Kept returning nulls. So I did it like this:

Guid siteID = properties.SiteId;
Guid webID = properties.ListItem.Web.ID;
Guid listID = properties.ListId;
Guid listItemID = properties.ListItem.UniqueId;
     using (SPSite site = new SPSite(siteID))
          using (SPWeb web = site.OpenWeb(webID))
                SPList list = web.Lists[listID];
                SPListItem item = list.Items[listItemID];
                string userValue = (string)item["Reported By User"];
                SPFieldUserValue fieldUserValue = new SPFieldUserValue(web, userValue);
                SPUser user = fieldUserValue.User;
                string department = GetBusinessUnit(user, site);            
                item["Business Unit"] = department;

//subroutine to get profile info here

private string GetBusinessUnit(SPUser user, SPSite site)
    string busUnit = string.Empty;
        ServerContext serverContext = ServerContext.GetContext(site);
        UserProfileManager upm = new UserProfileManager(serverContext);
        UserProfile profile = upm.GetUserProfile(user.LoginName);
        busUnit = profile["Department"].ToString();
    catch (Exception ex)
         //add your own error handling here
        busUnit = ex.Message + " : " + errorArgs;
    return busUnit;


This I can guarantee will work because I ran it successfully myself. One note with error trapping: if you create the profile and use a field that has a null value in the user's mySite, there's nothing here to gracefully trap that at present, unless you don't mind your control displaying a honking big error message :)