Recently I had a need to pull all user profiles out of our SharePoint farm in order to push them into a middle-tier database that my team was building.  Since this would be run as a scheduled task on a machine that would not have SharePoint installed on it, I would have to use the SharePoint User Profile web service to do this.  Simple enough right?

So I set out to accomplish this.  I read a few blogs and came to the conclusion that the simplest way to achieve this is to get a profile count and iterate through each profile sequentially to get all the information.  Following the logic above, I came up with something like the following:

// Instantiate a UserProfile object
UserProfileService userService = new UserProfileService();
userService.Credentials = System.Net.CredentialCache.DefaultCredentials;

// Get a profile count
long profileCount = userService.GetUserProfileCount();

for( long i = 0; i < profileCount; i++ ) {
GetUserProfileByIndexResult getUserProfileByIndexResult = userService.GetUserProfileByIndex( i );
// Do your processing of the profile here
}

The above code worked great until we started attempting to tweak the Active Directory queries in our user profile import connections to minimize the amount of invalid accounts imported.  Once we started tweaking the queries and user profiles were frequently being removed and re-added into the profile store, we started to see one problem repeatedly while looping through our results.  We kept seeing a single user being retrieved for multiple indices even though there was only one record for that user in the user profile store.

So what was happening?  Turns out that the GetUserProfileByIndex method of the SharePoint user profile web service does not return profiles in a sequentially indexed fashion.  You must use the NextValue property of the GetUserProfileByIndexResult class to find out at what index the next user profile can be found.

Code that will successfully iterate through all user profiles properly is listed below:

// Instantiate a UserProfile object
UserProfileService userService = new UserProfileService();
userService.Credentials = System.Net.CredentialCache.DefaultCredentials;

// The first record can be retrieved by passing -1 into the web service
GetUserProfileByIndexResult getUserProfileByIndexResult = userService.GetUserProfileByIndex( -1 );

while( getUserProfileByIndexResult.UserProfile != null ) {
// Do your processing of the profile here
getUserProfileByIndexResult = userService.GetUserProfileByIndex( Convert.ToInt32( getUserProfileByIndexResult.NextValue ) );
}

Once I started using the code above, I noticed that our user profiles actually started at an index well above 30,000, but we only had a total of 8,000 profiles or so in our database!  This means that the block of code that sequentially loops through user profile indices would never even reach one of our active user profiles!

How To Properly Enumerate User Profiles using the SharePoint User Profile Web Service

4 thoughts on “How To Properly Enumerate User Profiles using the SharePoint User Profile Web Service

Leave a Reply