End of the year already?

Wow.. Christmas really came and went.. My last post was back in november when I had just returned from Gran Canaria after a nice relaxing week in the sun.

After that short interlude, I had my first speaking engagement at a company seminar in front of 100 delegates. I was incredibly nervous and got a little lost during my presentation, but held it in check enough to deliver the 1 hour demo on SharePoint and the collaborative advantages of working with Microsoft Lync and Exchange.

Since then I’ve also been working on some Facebook and Twitter integration for SharePoint, which turned out to be not as straight forward as I hoped. Aiming to get some of this written up in the new year and posted here as certainly the Facebook API is not very .Net friendly at all!

Finally I’ve also been investigating the possibility of using the User profile service as a means of storing information about employees that could be synced with external systems such as SAP. in this example I’m looking at storing an employees Annual Holiday entitlement, and then updating or reading that value through the object model. It’s during this process that I’ve come across a disturbing issue with updating a profile that’s marked as Admin editable only with quite a hacky workaround. (Found at http://wss.boman.biz/Lists/Posts/Post.aspx?ID=23)

So first off, I’ve made the property available by creating it to the User Properties through Central Admin. It’s a simple integer property called HolidayEntitlement. At present I’m not importing the value from anywhere as I intended just pushing a value in from code. The key thing here though is that the user must NOT be able to edit this themselves. So, when we create the property, we make sure that the ‘”Do not allow users to edit values for this property” option is well and truly ticked!

With the property created, a short section of code gets the User profile for the current user, and then iterates through the properties showing their name and values:- (outputzone is just an ASP:Label defined in the user control so that I can write quickly to the page output.)

SPUser currUser = SPContext.Current.Web.CurrentUser;
SPServiceContext serviceContext = SPServiceContext.GetContext(SPContext.Current.Site);
UserProfileManager upm = new UserProfileManager(serviceContext);
UserProfile up = upm.GetUserProfile(currUser.LoginName);
ProfileSubtypePropertyManager pstpm = up.Properties;
foreach (ProfileSubtypeProperty pstp in pstpm)
{
                    outputZone.Text += "Property:- " + pstp.Name + br;

                    string propVal = string.Empty;

                    if (up[pstp.Name].Value != null)
                    {
                        propVal = up[pstp.Name].Value.ToString();
                    }
                    outputZone.Text += propVal;
                    outputZone.Text += br;

                    outputZone.Text += "Unprotected:- " + pstp.IsUserEditable + br;
}

So when you place this webpart on a page, you should see an output of all the properties currently mapped for the current user. If all went ok, You should see our “HolidayEntitlement” property with an empty value and “Unprotected:- False”

If we now add a short section of code to update the Holiday Entitlement to 25, we’ll receive a “Property Not Editable. This property can only be modified by an administrator” exception. Exactly what I would expect given that I marked the property as not editable by the end user. To get around this, we’ll crack open an Elevated Priviledges section with a new SPSite object and perform the update:-

SPSecurity.RunWithElevatedPrivileges(delegate()
{

     using (SPSite elevSite = new SPSite(SPContext.Current.Site.ID))
     {

          SPServiceContext elevServiceContext = SPServiceContext.GetContext(elevSite);
          UserProfileManager elevUpm = new UserProfileManager(serviceContext);
          UserProfile elevUp = elevUpm.GetUserProfile(currUser.LoginName);
         
          if (elevUp["HolidayEntitlement"].Value == null)
          {
               elevUp["HolidayEntitlement"].Value = 25;
               elevUp.Commit();
          }
});

That should do it, one quick page refresh later and we see a nice exception “Property Not Editable. This property can only be modified by an administrator”. Hang on, didn’t we just solve this by wrapping our code in an elevated priviledges block? Well no, it would appear not. for some reason, the userProfile update is still trying to run under the context of the connected user, despite elevating priviledges. After a short search on the net, I cam across the post linked at the top regarding a bit of a dirty hack to get around this issue. Basically we have to Null the current HTTPContext before the update, then recreate it afterwards as per the code below.

SPSecurity.RunWithElevatedPrivileges(delegate()
{

     using (SPSite elevSite = new SPSite(SPContext.Current.Site.ID))
     {

          SPServiceContext elevServiceContext = SPServiceContext.GetContext(elevSite);
          UserProfileManager elevUpm = new UserProfileManager(serviceContext);
          UserProfile elevUp = elevUpm.GetUserProfile(currUser.LoginName);

          HttpContext savedContext = HttpContext.Current;
          HttpContext.Current = null;
         
          if (elevUp["HolidayEntitlement"].Value == null)
          {
               elevUp["HolidayEntitlement"].Value = 25;
               elevUp.Commit();
          }

          HttpContext.Current = savedContext
});

This works and I’m not exactly clear why, so kinda hoping some of my SharePoint colleagues can help me understand what’s going on.

Paul.

Leave a Reply

Your email address will not be published.

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.