Domanda

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.

È stato utile?

Soluzione

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.

Altri suggerimenti

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();
          }
}

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?

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);
} 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a sharepoint.stackexchange
scroll top