Here is the solution I have used. I adapted it from the following blog post: http://pholpar.wordpress.com/2010/04/16/getting-the-my-site-host-url-from-code/
/// <summary>
/// Retreives the search centre URL as defined in the User Profile Service Application
/// Adapted from http://pholpar.wordpress.com/2010/04/16/getting-the-my-site-host-url-from-code/
/// </summary>
/// <param name="site">Site Collection</param>
/// <returns>URL of Search Centre</returns>
private string GetSearchCentreUrl(SPSite site)
{
if (site == null)
{
throw new ArgumentNullException("site", "The Site Collection provided must not be null");
}
string searchCentreUrl = null;
// hack to get the Microsoft.Office.Server.UserProfiles assembly
Assembly userProfilesAssembly = typeof(UserProfile).Assembly;
// UserProfileApplication and UserProfileService are internal classes,
// so you cannot get them directly from Visual Studio
// like I do with the SPServiceCollection type
Type userProfileApplicationType = userProfilesAssembly.GetType("Microsoft.Office.Server.Administration.UserProfileApplication");
Type userProfileServiceType = userProfilesAssembly.GetType("Microsoft.Office.Server.Administration.UserProfileService");
Type spServiceCollectionType = typeof(SPServiceCollection);
// first we call
// SPFarm.Local.Services.GetValue<UserProfileService>()
MethodInfo getValueMethod = spServiceCollectionType.GetMethod("GetValue",
BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null
);
if (getValueMethod != null)
{
// get the generic version of GetValue method
MethodInfo methodInvokeGetValueGeneric = getValueMethod.MakeGenericMethod(userProfileServiceType);
if (methodInvokeGetValueGeneric != null)
{
Object userProfileService = methodInvokeGetValueGeneric.Invoke(SPFarm.Local.Services, null);
System.Reflection.PropertyInfo applicationsProperty = userProfileServiceType.GetProperty("Applications", BindingFlags.NonPublic | BindingFlags.Instance);
if ((applicationsProperty != null) && (userProfileService != null))
{
// Microsoft.Office.Server.Administration.UserProfileApplicationCollection
Object userProfileApplicationCollection = applicationsProperty.GetValue(userProfileService, null);
if (userProfileApplicationCollection != null)
{
foreach (Object userProfileApplication in (IEnumerable)userProfileApplicationCollection)
{
// you could compare the id for the service application id
// it is useful if there are multiple user profile service application instances
// since it is not common I ignore the condition now and exit after the first item
//System.Reflection.PropertyInfo pi_Id = userProfileApplicationType.GetProperty("Id", BindingFlags.Public | BindingFlags.Instance);
//if (pi_Id != null)
//{
// Guid id = (Guid)pi_Id.GetValue(userProfileApplication, null);
//if (appId == id)
//{
Type[] parameterTypes = new Type[2] { typeof(SPUrlZone), typeof(SPServiceContext) };
MethodInfo getSearchCentreUrlMethod = userProfileApplicationType.GetMethod("GetSearchCenterUrl",
BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null
);
if (getSearchCentreUrlMethod != null)
{
searchCentreUrl = getSearchCentreUrlMethod.Invoke(userProfileApplication, new object[] { site.Zone, SPServiceContext.GetContext(site) }) as string;
}
break;
//}
//}
}
}
}
}
}
return searchCentreUrl;
}