Now and then I have to retrieve information from the User Profile Service, such as user profiles. For this I use the UserProfileManager class. But, when the User Profile Service is not available for some reason, the code throws an UserProfileApplicationNotAvailable exception. You could use try..catch strategy to handle alternative code, or you could write some awesome code that checks if a service is available.
Consider the following code snippet:
UserProfileManager upm = new UserProfileManager(SPServiceContext.Current); if (upm.UserExists(accountName)) { UserProfile profile = upm.GetUserProfile(accountName); userProfilePageUrl = profile.PublicUrl.AbsoluteUri; }
When the User Profile Service is up and running, the code will run just fine. When the service is stopped…
….then the code will throw the UserProfileApplicationNotAvailable exception on the first line of code. If this code is part of a custom web part, then it depends on how the exception handling is done whether the whole page is blocked or not with the familiar message: Something went wrong.
When searching the net you will find plenty of examples how to retrieve services and their status using the cmdlet Get-SPServiceInstance.
But that’s PowerShell, I needed C# code.
The SPFarm object is the one I needed. From this object I can retrieve all services. Let’s take a look at the following code snippet:
public static bool IsOnlineService(string typeName) { bool isOnline = false; SPService service = SPFarm.Local.Services.FirstOrDefault(s => s.TypeName.Equals(typeName)); if (service != null ) { SPServiceInstance instance = service.Instances.FirstOrDefault(i => i.Status == SPObjectStatus.Online); isOnline = (instance != null); } return isOnline; }
This methods takes a string argument that contains the type name of the service (like shown in the PowerShell cmdlet screenshot). Then I call the SPFarm.Local.Services and use some LINQ magic to get the one I need. For example, the User Profile Service.
If a service is found I retrieve all the instances of that service and once again with some LINQ magic I get the ones with a status Online. If an instance is found, then the service is online. Well, I consider this the basics and I can image that their other scenarios to consider (authorization perhaps).
Now we can change our first code snippet to something like this:
UserProfileManager upm = null; if (Utilities.IsOnlineService("User Profile Service")) { upm = new UserProfileManager(SPServiceContext.Current); if (upm.UserExists(accountName)) { UserProfile profile = upm.GetUserProfile(accountName); userProfilePageUrl = profile.PublicUrl.AbsoluteUri; } } else { // Handle it your way... }
Works like a charm. Happy coding!