Updated SPSite.RootWeb Dispose Guidance


I have recently been working directly with the Microsoft Office SharePoint Server 2007 (MOSS 2007) Product Group as well as several Subject Matter Experts in the Microsoft Services field to help clarify some Dispose edge cases which have been causing confusion which have surfaced in the MOSS Developer community.  Taking a closer look at the RootWeb Dispose Best Practice listed in the MSDN white paper Best Practices: Using Disposable Windows SharePoint Services Objects there is an new exception to the SPSite.RootWeb Dispose guidance.

Do not explicitly call Dispose() on the SPSite.RootWeb property.  The dispose cleanup will be handled automatically by the SharePoint and the .NET framework.  For existing SharePoint customizations removal of explicit RootWeb Dispose is recommended to avoid an edge case condition where the SPContext.Current.Web has equality to the SPSite.RootWeb.  Problems can occur when disposing RootWeb when obtained from any variation of SPContext (For Example: SPContext.Site.RootWeb, SPContext.Current.Site.RootWeb and GetContextSite(Context).RootWeb ).  Note the owning SPSite object must be properly Disposed (or not Disposed in the case of SPContext) as described here – SharePoint 2007 and WSS 3.0 Dispose Patterns by Example.

In addition, SPSite properties LockIssue, Owner, and SecondaryContact internally used the RootWeb property.  Based on the updated guidance for RootWeb no explicit Dispose on any of these properties are required.  Again, note the same dependency on properly Disposing the owning SPSite object is in effect.

public void RootWebBestPractice()
{
    // Exception to "Best Practices: Using Disposable Windows SharePoint Services Objects" White paper

    // Example 1 - new SPSite
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        SPWeb rootWeb1 = siteCollection.RootWeb;
        // No explicit rootWeb1 dispose required
    }  // siteCollection automatically disposed by implementing using()
    // rootWeb1 will be Disposed by SPSite

    // Example 2 - SPContext and SPControl
    SPWeb rootWeb2 = SPContext.Current.Site.RootWeb;
    // Also would apply to SPControl.GetContextSite(Context);
    // No explicit rootWeb2 dispose required because it's obtained from SPContext.Current.Site
}

Comments (9)

  1. AndersR says:

    An really excellent initiative!

    The API docs are more than lacking (they are misguiding, really) regarding the methods that call unmanaged code.

    Keep up the good work!

    Thanx

    Anders Rask

  2. michaelkc says:

    One thing that seems to be missing from all the papers on IDisposable Sharepoint objects is guidance regarding event receivers, e.g. ItemAdded has an IDisposable SPItemEventProperties passed to it, containing a ListItem property which itself has a lot of IDisposable properties.

    Any chance of an update addressing this issue?

  3. Roger Lamb says:

    michaelkc, I will be working on additional edge cases with the product group and other subject matter experts in the field at Microsoft and post results here as they become available.  Thanks for your suggestion.

  4. Barmaleyer says:

    Is it related to latest WSS service pack or Infrastructure update? Should I continue to dispose RootWeb as it was suggested before on servers that operate MOSS with no service pack installed yet?

  5. SPSite and SPWeb implement the IDisposable interface

  6. To Dispose Or Not To Dispose….That Is The Question

  7. mdressel says:

    Isn’t there a way to code this such that we are able to handle all cases.  For example, the code below seems like it would check to see if the current web (retrieved from the RootWeb property) is equivilant to the SPContext.Current.Web obejct.  Does this work or is there no real programmatic way to handle this?  

    Right now we have code that is used in a variety of ways (event recievers, stsadm commands, application pages) which all use the RootWeb property.  Therefore, I have no way say while I am writing my code that .RootWeb will always equate to SPContext.Current.Web.

    SPWeb web = SomeSite.RootWeb;

    try

    {

    …..

    }

    finally

    {

       if(web != null

         && (SPContext.Current == null

                || (SPContext.Current != null

                     && web != SPContext.Current.Web))

       {

           web.Dispose();

       }

    }

  8. mdressel says:

    Please ignore my previous post… I did not fully review the code example and the explination was not clear to me.  I now realize that all I need to do is ensure that the SPSite object is being disposed of properly and the RootWeb property shoudl never be disposed.