Here’s the scenario.
You need to retrieve the total number of user profiles in SharePoint. The API has a property for that in the UserProfileManager class. You could just write some code like this:
UserProfileManager profileManager = new UserProfileManager(serviceContext);
long ProfileCount = profileManager.Count;
But the problem is that in order to retrieve this you need to have admin privileges on the User Profile Service. So the logical way of doing this is to run the code with Elevated privileges and ensure the identity used by the application pool of your site has admin privileges on the User Profile service. So I’ve tried that using the code below:
SPSite siteColl = SPContext.Current.Site;
try{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite ElevatedsiteColl = new SPSite(siteColl.ID))
{
SPServiceContext serviceContext = SPServiceContext.GetContext(ElevatedsiteColl);
UserProfileManager profileManager = new UserProfileManager(serviceContext);
ProfileCount = profileManager.Count;
}
});
}
catch (Exception ex)
{
LogException(ex);
}
Testing the code running under an Admin account it was fine (because it was the same account used by the site’s application pool). But when I tested the code using a regular user this code should still run fine (because I was running it elevated). Unfortunately that’s not what happened. For some weird reason seems that the SharePoint API was trying to impersonate the current user thus throwing an exception and showing an Access Denied error which said
Access Denied: Only an administrator may retrieve a count of all users.
The Workaround
Basically my workaround is to set the current HttpContext to null inside the code, but keeping the existing context in a temp variable so I can revert it back once I run the snippet. You have to revert it back to the original context otherwise you are going to get a lot of errors. The code looks like this:
SPSite siteColl = SPContext.Current.Site;
HttpContext tempCtx = HttpContext.Current;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate() {
using (SPSite ElevatedsiteColl = new SPSite(siteColl.ID))
{
SPServiceContext serviceContext = SPServiceContext.GetContext(ElevatedsiteColl);
HttpContext.Current = null;
UserProfileManager profileManager = new UserProfileManager(serviceContext);
ProfileCount = profileManager.Count;} });
}
catch (Exception ex){ LogException(ex);}
finally{ HttpContext.Current = tempCtx;}
Using the code above I could retrieve the count even using a regular user (no admin access) .
I hope this saves some time on your side and avoid some head banging on the wall
Have a nice one !