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.