9

I have a property in the user profile. This property has privacy settings equal to "Private" (or "Only Me" if working through UI). It means that value for this property will be shown only to you or admin of user profile application. I want to get value of this property in a web part under any other user through code. I use this code, but it's not working (property value equals to null due to privacy settings, but it's not null actually):

SPSecurity.RunWithElevatedPrivileges(delegate
{
    using (var site = new SPSite(SPContext.Current.Site.ID))
    {
        var manager = new UserProfileManager(SPServiceContext.GetContext(site));
        var profile = manager.GetUserProfile(@"domain\name");
        var value = profile["my_property_name"].Value;
    }
});

Is it possible to get profile property with Private privacy through code?
Thanks in advance.

2
  • Will changing the privacy value to other than "Private" make the property in question work?
    – Jussi Palo
    Commented Jan 30, 2012 at 13:36
  • Yes, when changing to public I can read value, when switch again to private - null returns as value. Commented Jan 30, 2012 at 14:49

4 Answers 4

5

Finally I figured it out. UserProfileManager internally checks HttpContext.Current.User to determine if current user can view property value. The trick is to replace context and user (if HttpContext.Current.User is null, null reference thrown in UserProfileManager constructor, so this is required). The final code looks like this one:

SPSecurity.RunWithElevatedPrivileges(delegate
{
    var context = HttpContext.Current;
    HttpContext.Current = new HttpContext(new HttpRequest(string.Empty, SPContext.Current.Site.Url, string.Empty), new HttpResponse(new StringWriter()));
    HttpContext.Current.User = new GenericPrincipal(WindowsIdentity.GetCurrent(), new string[0]);
    var manager = new UserProfileManager(SPServiceContext.GetContext(HttpContext.Current));
    var profile = manager.GetUserProfile(@"domain\name");
    var value = profile["my_property"].Value;
    HttpContext.Current = context;
});  

RunWithElevatedPrivileges required because only under elevated code we can guarantee that WindowsIdentity.GetCurrent() returns application pool account. And this account should have sufficient permissions for user profile application (to read private properties).
It works, but I only doubt if this is the best and safe solution.

0
1

Have you tried to open context as an user which profile do you want to retrieve?

SPUser user = web.EnsureUser(@"domain\name");
SPUserToken token = user.UserToken;
using (SPSite site = new SPSite(SPContext.Current.Site.ID, token ))
{

}

In this case try something like this

public class ContextSwitcher: IDisposable
{
           private HttpContext _temp;
           private SPSite _site;
           private SPWeb _web;

           public ContextSwitcher(string url, string username)
          {
                      SPUser user = web.EnsureUser(username);
                      SPUserToken token = user.UserToken;

                      _site = new SPSite(url, token);
                      _web = _site.OpenWeb();
                      _temp = HttpContext.Current; 

                     HttpRequest request = new HttpRequest("", _web.Url, "");
                     request.Browser = new HttpBrowserCapabilities();
                     HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
                     HttpContext.Current.Items["HttpHandlerSPWeb"] = _web;
          }

          public void Dispose()
         {
                     HttpContext.Current = _temp;
                     if (_web != null) _web.Dispose();
                     if (_site != null) _site.Dispose();
          }
}
3
  • I tried your code, it's not working. It seems that HttpContext.Current.User checks internally by UserProfileManager to determine if you can see property's value. Playing with HttpContext now :) Commented Jan 30, 2012 at 15:51
  • @Kai, I've updated my answer. Try to use this code )
    – Alexander
    Commented Jan 30, 2012 at 16:45
  • HttpContext.Current.User is null in your example, this cause null reference in UserProfileManager constructor, so this not working. I found a solution at least, see my answer. Commented Jan 31, 2012 at 7:47
0

As far as I know this is how it should work. A private property is meant to be so, also in code and definitely when another user tries to get the value.

With all respect, what are you trying to accomplish? I understand you are not allowed to change the privacy setting of the property?

4
  • Yep, I am not allowed to change privacy settings, it must remain private, but I want to get access to this property's values using code. I supposed that only RunWithElevated will be sufficient, but in SharePoint not all so easy.. ) Commented Jan 30, 2012 at 16:55
  • I agree, this is SharePoint working as designed. If you need the access you have to run under an admin account. Can you describe why your requirements are set up this way?? Commented Jan 30, 2012 at 19:00
  • I see original question as a valid technical question. I run into similar ones quite often with SharePoint and RunWithElevatedPrivileges is relatively often the only way to implement the requirements; this time only it is not enough making the question even more interesting :)
    – Jussi Palo
    Commented Jan 30, 2012 at 20:23
  • @Matthew McDermott, some data persisted in user profile properties from external system (using BCS synchronization connection). Logically, some of this properties should be private and we don't want to make it public, but I need to use values of this properties in code. Commented Jan 31, 2012 at 7:51
0

It seems that some of the properties of HttpContext used by MOSS in static classes (i.e. ServerContext) are not initialised properly. The code makes it possible for MOSS to retrieve “current web” (SPContext.Current.Web) and “current servercontext”.

You may need to use this in case you are getting an exception stating UserProfile.Parent Operation is not valid due to the current state of the object

if (HttpContext.Current != null)
{
      if (HttpContext.Current.Items["HttpHandlerSPWeb"] == null)
           HttpContext.Current.Items["HttpHandlerSPWeb"] = ElevatedSite.RootWeb;
      if (HttpContext.Current.Items["Microsoft.Office.ServerContext"] == null)
          HttpContext.Current.Items["Microsoft.Office.ServerContext"] = SPServiceContext.GetContext(ElevatedSite);
} 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.