Roger Lamb has posted another edge case in the pursuit of leak-free object model code: UserProfile.PersonalSite. To help follow his best practices, I offer another round of extension methods. First, for UserProfile:
public static void ProcessPersonalSite(this UserProfile profile, Action<SPSite> action)
{
using (SPSite site = profile.PersonalSite)
{
action(site);
}
}
public static T SelectFromPersonalSite<T>(this UserProfile profile, Func<SPSite, T> selector)
{
using (SPSite site = profile.PersonalSite)
{
return selector(site);
}
}
Usage:
void PersonalSiteNoLeak()
{
// open a site collection
using (SPSite siteCollection = new SPSite("http://moss"))
{
UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
UserProfile profile = profileManager.GetUserProfile("domain\\username");
profile.ProcessPersonalSite(personalSite =>
{
// Process personalSite
});
}
}
int CountContextPersonalSiteWebs()
{
UserProfile myProfile = ProfileLoader.GetProfileLoader().GetUserProfile();
return myProfile.SelectFromPersonalSite(personalSite =>
{
return personalSite.AllWebs.Count;
});
}
I’ve also encapsulated the verification logic for accessing a MySite web part’s PersonalSite, with variations for projection and with/without exceptions:
public static void ProcessPersonalSite(this WebPart webpart, Action<SPSite> action)
{
IPersonalPage personalPage = webpart.Page as IPersonalPage;
if (personalPage == null)
throw new SPException("Unable to access personal site. Invalid page.");
if (personalPage.IsProfileError)
throw new SPException("Unable to access personal site because of a profile error.");
action(personalPage.PersonalSite);
}
public static T SelectFromPersonalSite<T>(this WebPart webpart, Func<SPSite, T> selector)
{
IPersonalPage personalPage = webpart.Page as IPersonalPage;
if (personalPage == null)
throw new SPException("Unable to access personal site. Invalid page.");
if (personalPage.IsProfileError)
throw new SPException("Unable to access personal site because of a profile error.");
return selector(personalPage.PersonalSite);
}
public static bool TryProcessPersonalSite(this WebPart webpart, Action<SPSite> action)
{
IPersonalPage personalPage = webpart.Page as IPersonalPage;
if (personalPage == null || personalPage.IsProfileError)
return false;
action(personalPage.PersonalSite);
return true;
}
public static bool TrySelectFromPersonalSite<T>(this WebPart webpart, Func<SPSite, T> selector, out T value)
{
value = default(T);
IPersonalPage personalPage = webpart.Page as IPersonalPage;
if (personalPage == null || personalPage.IsProfileError)
return false;
value = selector(personalPage.PersonalSite);
return true;
}
Usage:
protected override void CreateChildControls()
{
base.CreateChildControls();
this.ProcessPersonalSite(personalSite =>
{
// Process personalSite
});
}
As always, feedback is encouraged.

