Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

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.

share|improve this question
    
Will changing the privacy value to other than "Private" make the property in question work? –  Jussi Palo Jan 30 '12 at 13:36
    
Yes, when changing to public I can read value, when switch again to private - null returns as value. –  Kai Jan 30 '12 at 14:49
add comment

4 Answers

up vote 5 down vote accepted

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.

share|improve this answer
    
BIG help to me this, thanks. +1. –  DeeMac Nov 1 '12 at 9:18
add comment

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();
          }
}
share|improve this answer
    
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 :) –  Kai Jan 30 '12 at 15:51
    
@Kai, I've updated my answer. Try to use this code ) –  Alexander Jan 30 '12 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. –  Kai Jan 31 '12 at 7:47
    
@Kai, thanks, I will keep it in mind :) –  Alexander Jan 31 '12 at 8:26
add comment

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?

share|improve this answer
    
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.. ) –  Kai Jan 30 '12 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?? –  Matthew McDermott Jan 30 '12 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 Jan 30 '12 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. –  Kai Jan 31 '12 at 7:51
add comment

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);
} 
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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