none
UserProfileConfigManager.ConnectionManager.Count always returning 0 despite there actually being 3 connections. RRS feed

  • Question

  • Hi all,

    Sorry to trouble you, i am having real issues accessing the connections within my user service application, it does not seem to find them at all when using the following code.

    using (var site = properties.Feature.Parent as SPSite)
    {
    SPServiceContext context = SPServiceContext.GetContext(site);                 
    UserProfileConfigManager userConfigManager = new UserProfileConfigManager(context);
    int i = userConfigManager.ConnectionManager.Count;
    }

    I always get 0 even though i have 3 connections, 2 ad and 1 BDC. Is this likely to be a bug or am i barking up the wrong tree? Basically i would like to get the connection object so i can create the AD mappings via a feature within a MySite site definition.

    Many thanks
    Tim

    Friday, March 19, 2010 5:16 PM

All replies

  • Any ideas on this one? Would be really useful to be able to create AD mapping via code otherwise there will be dependencies on the configuration with my site definition.

    Thanks everyone
    Tim

    Monday, March 22, 2010 10:47 AM
  • I have the same problem. Any solution?

    Jim

     

    Friday, February 11, 2011 6:05 PM
  • Off the wall suggestion, but check your service application associates in Central Admin and make sure the user profile service is associated with the web applications your running the code on.

    Application Management -> Configure Service application Associations ->

    Click the web application in question in the left list, and make sure the Right User Profile Service is associated with it.

     

    I've seen farms with multiple user profile services and they have the wrong one associated with their site.  In #1 they have 3 connections and in #2 they don't have any.  However #2 is associated with the site so connection manager thinks their are no connections.

     

     

    • Proposed as answer by Ryan T Mann Friday, February 11, 2011 10:07 PM
    • Unproposed as answer by Ryan T Mann Thursday, June 23, 2011 6:09 PM
    Friday, February 11, 2011 8:58 PM
  • I had the same issue.

    Using reflector to debug it turns out that the account running the code was getting access denied when working with resources at a lower level.

    The fix was to make sure the account running the code had the 'Manage Profiles' permission.

    • Central Admin
    • Manage Service Application
    • Highlight your [Profile Service] (don't click through)
    • Click Administrators in the ribbon
    • Make sure account running code has 'Manage Profiles' ticked

    With this setting Count then returned 1 and I could happily use the connection to create a mapping.

    Hope it helps others!

    • Proposed as answer by Tezler Thursday, June 23, 2011 2:07 PM
    Thursday, June 23, 2011 2:07 PM
  • You can grant the ApplicationPool Identity Manager Profile permission, then use a //hack to get the ProfileManager to run elevated.

     

    SPSecurity.RunWithElevatedPermissions(delegate()

    {

        using (SPSite site = new SPSite("http://blah.com"))

        {

             HttpContext old = HttpContext.Current;

             HttpContext.Current = null;        

             SPServiceContext context = SPServiceContext.GetContext(site);

             UserProfileManager upm = new UserProfileManager(context, true); //runs user profile manager in admin mode (if AppPool identity is a UserProfile Manager.)

             UserProfile profile = upm.GetUserProfile("encodedClaimAccountNameStringHere");

             profile["PreferredName"].Value = "Users New DisplayName"; //this property is not user editable, so this is a good test.

             HttpContext.Current = old;

        }

    });

    The issue is the CheckPermissions function in both the UserProfileManager and in the ProfileValueCollection on the returned UserProfile, checks HttpContext.Current.Identity to get the user to see if they have permissions to get the desired profile and edit the property.

    Setting HttpContext.Current to null causes it to use the Impersonated identity instead (the application pool in this scenario).

    This bug was supposedly fixed in SharePoint Server 2007 in a ServicePack from what I've heard, so I don't know why it exists in sharepoint server 2010, unless sharepoint server 2010 was built on a version of 2007 that didn't have the bug fix.


    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction
    Thursday, June 23, 2011 5:22 PM
  • Nice little hack with setting the HttpContext to null, i have now been able to eliminate my far more nasty approach.

    Thanks for this :)

    Tim

    Friday, July 1, 2011 2:43 PM
  •  

    Heres an example of a helper class I use for this bug.

     

     

    public class ProfilePropertyNotFoundException : Exception
    {
      public ProfilePropertyNotFoundException(string PropertyName)
        : base("Unable to find a profile property by the name: " + PropertyName) { }
    }
    
    public static class ProfileHelper
    
    {
    	public delegate void ElevatedClearContextDelegate(HttpContext previousContext);
    
    	public delegate void UserProfileDelegate(UserProfile profile, params object[] parameters);
    
        public static void RunWithClearContext(ElevatedClearContextDelegate codeToRunInClearContext)
        {
          Exception ex = null;
          HttpContext ctx = null;
          if (HttpContext.Current != null)
          {
            ctx = HttpContext.Current;
            HttpContext.Current = null;
          }
          try
          {
            codeToRunInClearContext(ctx);
          }
          catch (Exception exception)
          {
            ex = exception;
          }
          finally
          {
            if (ctx != null)
              HttpContext.Current = ctx;
    
            if (ex != null)
            {
              throw ex;
            }
          }
        }
    
        public static T GetProfileValue<T>(UserProfile profile, string profileField)
        {
          object FieldValue = null;
    
          Exception throwEx = null;
    
          if (profile != null)
          {
            try
            {
              RunWithClearContext(delegate(HttpContext oldContext)
              {
                if (profile[profileField] != null && profile[profileField].Value != null)
                  FieldValue = (T)profile[profileField].Value;
              });
            }
            catch (Exception exc)
            {
              throwEx = exc;
            }
          }
          else
          {
            if (throwEx == null)
              throwEx = new ArgumentException("profile");
          }
          if (throwEx != null)
            throw throwEx;
          return (T)FieldValue;
        }
    
        public static void SetProfileValue(UserProfile profile, string ProfileField, object Value)
        {
          if (profile == null)
            throw new ArgumentNullException("profile");
    
          Exception throwEx = null;
    
          try
          {
            RunWithClearContext(delegate(HttpContext oldContext)
            {
              if (profile != null)
              {
                if (profile[ProfileField] != null)
                {
                  profile[ProfileField].Value = Value;
                  profile.Commit();
                }
                else
                  throwEx = new Exceptions.ProfilePropertyNotFoundException(ProfileField);
              }
            });
          }
          catch (Exception ex)
          {
            throwEx = ex;
          }
          if (throwEx != null)
            throw throwEx;
        }
    
        public static void GetCreateUserProfile(string siteUrl, string LoginName, bool ignorePrivacy, bool runElevatedRegardlessOfPrivacy, UserProfileDelegate codeToUseProfile)
        {
          if (string.IsNullOrEmpty(siteUrl))
            throw new ArgumentNullException("SiteUrl");
          if (string.IsNullOrEmpty(LoginName))
            throw new ArgumentNullException("LoginName");
          if (codeToUseProfile == null)
            throw new ArgumentNullException("codeToUseProfile");
    
          if (ignorePrivacy || runElevatedRegardlessOfPrivacy)
          {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
              using (SPSite contextSite = new SPSite(siteUrl))
              {
                UserProfile profile = null;
                RunElevatedAndClearContext(delegate(HttpContext oldContext)
                {
                  SPServiceContext context = SPServiceContext.GetContext(contextSite);
                  UserProfileManager upm = new UserProfileManager(context, true);
                  try
                  {
                    if (upm.UserExists(LoginName))
                      profile = upm.GetUserProfile(LoginName);
                    else
                      profile = upm.CreateUserProfile(LoginName);
                  }
                  catch (Exception ex)
                  {
                    profile = null;
                  }
                });
                codeToUseProfile(profile, contextSite);
              }
    
            });
    
          }
          else
          {
            //Don't run elevated.
            try
            {
              using (SPSite contextSite = new SPSite(siteUrl))
              {
                try
                {
                  UserProfile profile = null;
                  SPServiceContext context = SPServiceContext.GetContext(contextSite);
                  UserProfileManager upm = new UserProfileManager(context, ignorePrivacy);
                  if (upm.UserExists(LoginName))
                    profile = upm.GetUserProfile(LoginName);
                  else
                    profile = upm.GetUserProfile(LoginName);
    
                  codeToUseProfile(profile, contextSite, context, upm);
                }
                catch (Exception ex4)
                {
                  if (contextSite != null)
                    contextSite.Dispose();
                  throw new CriticalProfileError(ex4.Message, ex4);
                }
              }
            }
            catch (Exception ex3)
            {
              if (ex3.GetType() != typeof(CriticalProfileError))
                throw new CriticalProfileError(siteUrl + " is not a valid SPSite.", ex3);
            }
          }
        }
    }
    

     


    Example,

    string AccountName = "domain\\user";
    
    //The first parameter is the site url you want to use to get the context to the UserProfile Service Application.
    //The second parameter is the encoded claim ('aka login name, aka AccountName') of the user you want to get or create a user profile for
    //The third parameter tells it to ignore user privacy ("The application pool must be a user profile administrator").
    //The fourth parameter tells it to run all this code elevated even if you have ignorePrivacy set to true, e.g. It runs as ADMIN, but respects user profile privacy
    //The final parameter is a delegate it will call with the retrieved user profile and a params array containing the SPSite used for the call.
    ProfileHelper.GetCreateUserProfile(SPContext.Current.Site.Url, AccountName, true, true, delegate(UserProfile profile, object[] parameters)
    {
      SPSite passedInSiteElevated = parameters[0] as SPSite;
      
      //example of setting a Profile Property that is not user editable.
      ProfileHelper.SetProfileValue<string>(profile, "PreferredName", "IAmBob");
    
    });
    

    Final notes.

    You can resuse the SPSite the method spins up so you don't have to create rundundant elevated SPSites, but only if you pass in true, true, or false, true for the security booleans, otherwise it won't be an elevated site being passed back out.

    The SetProfileValue and GetProfileValue methods are necessary as well.  UserProfile executes the same permission function as the UserProfileManager so if you are running elevated it needs to have a Clear Context as well, those two methods in this helper class handle clearing the context and setting it back.  Should note as well, RunWithClearContext sets the context back even if the code it runs throws an error, it catches it, sets the context back , then throws it.

    My Blog: http://www.thesug.org/Blogs/ryan_mann1/default.aspx Website: Under Construction
    Friday, July 1, 2011 8:41 PM