user327045
user327045

Reputation: 45

sharepoint spweb and spsite disposal

I've been using the following code in a .NET 1.1 SharePoint 2003 environment and it works great:

            try
            {
                site = SPControl.GetContextSite(Context);
                web = site.OpenWeb();
                ...
            }
            catch (Exception export)
            {
                output.Write("Caught Exception: <br/><br/>");
                output.Write(export.Message + "<br><br>");
                output.Write(export.StackTrace);
            }
            finally
            {
                if (web != null)
                    web.Dispose();
                if (site != null)
                    site.Dispose();
            }

However, I'm currently porting the code to a .NET 2.0 SharePoint 2007 environment and I get the following error message:

"Trying to use an SPWeb object that has been closed or disposed and is no longer valid."

If I comment out the Dispose() code, it works fine. But won't this cause memory leaks? What's the best way to fix the problem?

Upvotes: 2

Views: 1458

Answers (4)

iambriansreed
iambriansreed

Reputation: 22241

Also a better way to do the above:

site = SPControl.GetContextSite(Context);
web = site.OpenWeb()

is the following:

SPSite site = SPContext.Current.Site;
SPweb web = SPContext.Current.Web;

No memory leaks here. Seriously though; going to 2007 not 2010?

Upvotes: 1

Ryan
Ryan

Reputation: 24422

When you get the SPSite object from GetContextSite you are getting an object that is shared with everything else running on that page.

After you Dispose of it other code is trying to use it - hence the error.

You should only Dispose objects that you create yourself and not ones that you get with GetContextSite.

The quick fix is (as Iambriansreed says) is to remove the finally block and replace the first two lines with.

SPSite site = SPContext.Current.Site; // Do you even need this?
SPweb web = SPContext.Current.Web;

Better performance and no memory leak as the SharePoint framework handles both creating and disposing of objects retrieved through SPContext.

However - its a complex and poorly understood subject so a thorough read through of the Best Practices: Using Disposable Windows SharePoint Services Objects and using the SPDisposeCheck tool is essential.

Upvotes: 2

Kobi
Kobi

Reputation: 138017

When handling disposable object, and SharePoint in particular, it is simpler to use using:

using(SPSite site = new SPSite("..."))
using(SPWeb web = site.OpenWeb("..."))
{

}

However, note that you should not dispose of elements that come from current context - they are shared, and disposing of them may cause this error. This is a common mistake, and in my opinion should have been handled better by the API.

See also - Using Disposable Windows SharePoint Services Objects:

SPContext objects are managed by the SharePoint framework and should not be explicitly disposed in your code. This is true also for the SPSite and SPWeb objects returned by SPContext.Site, SPContext.Current.Site, SPContext.Web, and SPContext.Current.Web.

Upvotes: 1

Coding Flow
Coding Flow

Reputation: 21881

Put your code in using statements which will auto call dispose when the objects go out of scope.e.g.

using(site = SPControl.GetContextSite(Context))
{
    using(web = site.OpenWeb())
    {
    //your code
    }
}

Upvotes: 0

Related Questions