3

How to get another user's followed sites, programmatically.

It seems that SPSocialFollowingManager followingManager = new SPSocialFollowingManager(userProfile, context); only works for the current user; for another user it always returns null.

I have tried to run with elevated privileges and it can't get the result for even the current user.

  • Did you try this blog.sharedove.com/adisjugo/index.php/2013/08/13/… – Aanchal Jun 21 '14 at 13:43
  • yes, I had tried, but it didn't work.This is only get the current login user's followed sites, not a specific user. when I login as different user name, it retuned empty list. – user29842 Jun 21 '14 at 13:51
  • Have you installed SP1? :) – Matt Connolly Jun 24 '14 at 22:02
  • I have SP1 installed and am noting the same behavior. I have also tried: impersonating via user tokens, temporarily nulling out HttpContext.Current, rebuilding HttpContext.Current entirely, using a UserProfileManager constructor overload that includes an ignore privacy flag, etc. I'm even unable to enumerate followed sites for all users using PowerShell or a console application, which is weird. – nsturdivant Jun 24 '14 at 22:21
  • Also, apparently you can get to another user's followed content via UserProfile.FollowedContent, but you cannot easily go from an array of FollowedItem objects to an array of SPSocialActor objects, as far as I know. – nsturdivant Jun 24 '14 at 22:26
2

A user's followed sites are stored within their personal site collection (i.e. their my site). By default, only the users themselves have access to their personal site collections (they are the primary site collection administrator). This is why the call to SPSocialFollowingManager.GetFollowed() isn't returning any SPSocialActor objects--the current user simply doesn't have access to the other user's personal site collection.

Depending on how your web applications are configured, elevating permissions may not be sufficient to resolve another user's followed sites because the application pool account under which the elevated code is running may not have access to the web application hosting the personal site collection of the user. Ultimately, SharePoint is doing the right thing here: security trimming the results of a list query based on the permissions of the current user.

If you grant the application pool account that your code is running under Read access to the My Site Host web application then you should be able to create an SPSite object representing the "non-current" user's personal site collection. With this SPSite object you can then new up an SPServiceContext and eventually call SPSocialFollowingManager.GetFollowed() in order to return the followed objects for that user. See this TechNet article for information on how to add a user policy to a web application (SharePoint 2013).

Okay, some code. In the snippet below, userName is the LoginName (i.e. account name) of the user whose followed sites we mean to get. This code is called from within a web part within a web application that is not configured as the My Site Host web application. However, the application pool account under which this code runs has been granted Read access to the My Site Host web application via Central Administration.

...

// get followed sites for a user that is not the current user
SPSecurity.RunWithElevatedPrivileges(() =>
{
    // resolve the user's profile
    UserProfile userProfile = null;

    using (var elevatedSite = new SPSite(SPContext.Current.Site.ID))
    {
        var serviceContext = SPServiceContext.GetContext(elevatedSite);
        var userProfileManager = new UserProfileManager(serviceContext);
        if (userProfileManager.UserExists(userName))
        {
            userProfile = userProfileManager.GetUserProfile(userName);
        }
    }

    if (userProfile != null)
    {
        // NOTE: for this to work properly the application pool account under which this code runs must have read permissions on the my site host web application

        // new up the user's personal site collection and get the user's followed sites            
        using (var personalSite = new SPSite(userProfile.PersonalSite.ID))
        {
            var personalServiceContext = SPServiceContext.GetContext(personalSite);
            // the next two lines are possibly redundant; these objects are recreated to ensure sanctity of context
            var personalUserProfileManager = new UserProfileManager(personalServiceContext);
            var personalUserProfile = personalUserProfileManager.GetUserProfile(userProfile.AccountName);
            var personalFollowingManager = new SPSocialFollowingManager(personalUserProfile, personalServiceContext);

            // if the user is following any sites, this array should not be empty
            var followedSites = personalFollowingManager.GetFollowed(SPSocialActorTypes.Sites);
        }
    }
});

...

No hacky nulling out or faking of HttpContext.Current necessary...

  • Can we get some feedback, @user29842? Please mark as answered or add additional follow up comments. Zombie questions hurt everyone. – nsturdivant Sep 9 '14 at 14:26
  • Thanks for your detailed answer, @nsturdivant, it toatally resolved this problem. :) – user29842 Sep 12 '14 at 8:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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