CODEDIGEST
Home » Articles
Search
 

Technologies
 

Sponsored links
 

CodeDigest Navigation
 

Technology News
No News Feeds available at this time.
 

Community News
No News Feeds available at this time.
 
SPException: Trying to use an SPWeb object that has been closed or disposed and is no longer valid

By Shai Patel
Posted On Mar 15,2009
Article Rating:
Be first to rate
this article.
No of Comments: 0
Category: Sharepoint
Print this article.

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

By Shai Petel, VP R&D KWizCom Corporation

 

Summary

KWizCom's VP R&D, Shai Petel explains how to handle a baffling error familiar to most SharePoint developers.

Shai Petel is a Microsoft Certified Trainer and Technology Specialist. He is also the main contributor to the KWizCom CRM SharePoint blog.

Just about any developer working long enough with SharePoint will, at some point, wake up in the middle of the night with the words "Memory Leak" echoing in through their head... No - it is not the cat's fault, and no it does not mean you forgot to take out the trash again... What did happen? You came across one of Microsoft's "best practices" articles regarding disposing of SPWeb and SPSite objects in SharePoint…

 

According to the original MS guidance, every SPWeb or SPSite object you create (or get) that was not initiated within the page's context (i.e. not SPContext.Current.Web and not SPControl.GetContextWeb(Context) ) must be disposed of.

 

It used to be that the "using" statement construct was recommended to avoid forgetting to dispose… in other cases you'd put up a flag and dispose of it at the end of your code's life cycle - either way was good enough.

 

Being the "good guys" that we are, we went over and updated all of our codes and components to match these guide lines.

And what happened? Every once in a while disposing these objects would cause baffling errors such as: "Trying to use a SPWeb object that has been closed or disposed and is no longer valid".

 

But hey, if we call SPContext.Current.Site.RootWeb - the best practices guidelines said we have to dispose of it! Same goes for SPContext.Current.Web.Site and SPContext.Current.Web.Site.RootWeb etc.

 

Recently I came across a great article by Roger Lamb showing a few updates from Microsoft regarding these disposable objects and recommendations.

 

So - pay close attention to these updates… it just might help you sleep through the night!

 

* When making a call to SPContext.Current.Web.Site.RootWeb - you now have to dispose only of the SPSite object: SPContext.Current.Web.Site!

 

Basically, you should NOT dispose of the SPSite.RootWeb object directly.

 

* When calling SPWeb.ParentWeb - you should NOT dispose of the ParentWeb object!

 

* Same goes to SPList.ParentWeb - do NOT dispose of the SPWeb object.

 

Other updates I found interesting (and frustrating) are:

* Calling SPWeb.AllWebs collection requires you to dispose of this collection object.

* Creating a new site by SPWeb.Webs.Add() - need to dispose of the web object returned.

* Calling GetLimitedWebPartManager() method? It will create a SPWeb object of its own and not dispose of it properly.

 

Please review the complete updated best practices guide at MSDN here:

http://msdn.microsoft.com/en-us/library/aa973248.aspx

 

I hope Microsoft will release an update for this issue soon.. Just thinking of all the code lines I wrote under the wrong best practices article is making me dizzy...




=~=~= Update =~=~=

Ok, this explains why it took me so long to find this problem...

I had this code in my web part, written according to the original best practices:

using(SPSite site = SPContext.Current.Web.Site)

{

    using(SPWeb web = site.RootWeb)

    {

        //Some code here...

    }

}

 

I cannot explain this but I only got this error on some sites, and on others it worked OK. Strange huh?

 

What I found is that this code will throw exception on any team site I created within a site collection that is not in the web application root path (i.e. sites under http://server/sites/*).

 

Anyway - according to the new guidelines, I should not dispose of the RootWeb object in this case. If I dispose of the SPSite object - it disposes of the RootWeb object -in this case my context web object...

So I updated my code to something like this and it worked:

 

SPWeb web = SPContext.Current.Site.RootWeb;//No disposing

//Some code here...

Similar Articles