Wednesday, June 6, 2007

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

This is an error that I'm sure most SharePoint developers have come across once or twice. Hopefully this will add some clarity to the error.

When dealing with the "SPWeb" object, it's all about Context... Literally!!

There are multiple ways to get an "SPWeb" object commonly you'll see:


SPSite site = new SPSite("http://servername");
SPWeb web = site.OpenWeb();


Another very common way to get a web object is the following:


SPWeb web = SPContext.Current.Web;


There's something very special about getting the web this way. The key to this method is that you're not opening a web. In fact, you're getting the web from current context which is being used by the page and other controls. That's fine...but what about disposal?

In general it's a best practice to dispose of object being used by wrapping disposable objects in a using statement. What would happen if you disposed of the web being used by the current context?


using(SPWeb web = SPContext.Current.Web)
{
.....
}

Well my friends, it's very possible to get the:

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


The best way to resolve this is to look for the places that you're using an "SPWeb" and make sure that you're not disposing of this object when it's from the current context.

For more information on best practices check out:

http://msdn2.microsoft.com/en-us/library/ms778813.aspx

Hope this helps,
~:)

13 comments:

Anonymous said...

Thanks for the wonderful tip!!!!

Anonymous said...

You, good sir, are the man!

Adrian said...

Thanks for this.

I just discovered something interesting:

On MSDN website it says that if you use SPSite.RootWeb property, you must dispose the returned object, since a new one is created and cached when it's accessed.

However they didn't mention that if you use the SPSite.RootWeb property, when the current SPWeb IS the root web, it will return the same object as SPContext.Current.Web!!! And of course if you dispose this, it causes this error!!

So, now I do this to dispose my SPWeb (to stop errors coming from the same code running in the root web)::

SPWeb w = SPContext.Current.Site.RootWeb;

if (w != SPContext.Current.Web) w.Dispose();


I hope this saves someone my headache.

Xopher said...

This works for me:
using (SPWeb web = SPContext.Current.Site.OpenWeb())

Anonymous said...

thanks, much appreciated.

Anonymous said...

Thanks

Per said...

Sometimes I just feel stupid =P Thank you for your tip!

Anonymous said...

You are the best...! Saved hours of headache going through code figuring out what the hell what is wrong and where is wrong...?

Naseem said...

Good post. Thanks...

Please note that you will get the same error (trying to use an SPWEB object!!!!...) if you try to dispose a site (not the spweb!!) created like this

SPSite site = SPContext.Current.Site;

For instance this code will break:

using (SPSite site = SPContext.Current.Site)
{
using (SPWeb web = site.OpenWeb())
{
// your code goes here
}
}

while this code works fine:

SPSite site = SPContext.Current.Site;

using (SPWeb web = site.OpenWeb())
{
// your code goes here
}

// no site.Dispose is needed.

Thanks
Naseeeem

stephen ogden said...

boh! this is exactly what I was looking for :) Thanks for the explanation

Anonymous said...

Thanks, very usefull!

Anonymous said...

hyperbole councilset optima reassurance utilize eligible artsliterary ingredients ambitious ammi username
servimundos melifermuly

Anonymous said...

politicians wetlands valanchery macromedia janet imparts acting minors andhra compulsively rhctotal
servimundos melifermuly