Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I've been trying to find documentation on how to correctly dispose webs and sites and I've come across this article which is quite good, but doesn't seem to cover all my scenarios.

My specific problem is with the following scenarios:

1: SPWeb.ParentWeb
2: SPWeb.Site.RootWeb
3: SPWeb.ParentWeb.ParentWeb...ParentWeb //several levels up

What is the correct way of disposing of these objects and does it make a difference whether the original web is a context web or not?

Edit: To be clear. I know I'm not supposed to dispose of the context web or site, my problem is specifically with ParentWeb and recursive calls to ParentWeb.

Edit: The article contains this line:

An earlier version of this article recommended that the calling application should dispose of the SPWeb.ParentWeb. This is no longer the official guidance. The dispose cleanup is handled automatically by the SharePoint framework.

with regard to ParentWeb. This is what confuses me. Should I or should I not dispose of parent webs and how far up the "tree" can I climb before I should start disposing webs? Does SharePoint open web objects all the way up to and including the root for every request to a sub web?

share|improve this question
1  
SPSite will call Dispose on all SPWeb objects created from it. As long as you never dispose a Context site, all will be fine. A lot of this is blown out of proportion these days, as SharePoint will happily reuse a Disposed SPSite or SPWeb object anyway. –  James Love Dec 6 '13 at 9:36

3 Answers 3

up vote 5 down vote accepted

Just to clarify on what you said with that statment,

An earlier version of this article recommended that the calling application should dispose of the SPWeb.ParentWeb. This is no longer the official guidance. The dispose cleanup is handled automatically by the SharePoint framework.

to my understanding:

from where you start the spweb object within the using statment that needs disposing it will dispose anything within it that is being called!

using (SPWeb web = site.OpenWeb())
{
   //call parent web within
}

the using statment handles the idisposable of any object tree within.

just to clarify what im talking about!

An earlier version of this article recommended that the calling application should dispose of the SPWeb.ParentWeb. This is no longer the official guidance. The dispose cleanup is handled automatically by the SharePoint framework.

Good Disposing

using (SPSite site = new SPSite(http://localhost)) 
{
    using (SPWeb web = site.OpenWeb())
    {
        SPList list = web.Lists["Announcements"];
        SPWeb parentWeb = list.ParentWeb; //No explicit dispose required.
    }
}

I think what they are refering to is sharepoint 2003 as it runs under older .net and older sharepoint.dll ;) but for 2007+ using the using statment that calls the idisposable of any newly created object within is the way to go!

obviously using the using statment is still fine grained, by that i mean disposing of recursive spweb within webs even within the using statment of the spweb will cause leaks:

Bad disposing

void WebsLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in outerWeb.Webs)
            {
                // SPWeb innerWeb leak.
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}

Good Disposing

void WebsNoLeak()
{
    using (SPSite siteCollection = new SPSite("http://moss"))
    {
        using (SPWeb outerWeb = siteCollection.OpenWeb())
        {
            foreach (SPWeb innerWeb in outerWeb.Webs)
            {
                try //Should be first statement after foreach.
                {
                    // ...
                }
                finally
                {
                    if(innerWeb != null)
                        innerWeb.Dispose();
                }
            }
        } // SPWeb object outerWeb.Dispose() automatically called.
    }  // SPSite object siteCollection.Dispose() automatically called. 
}

more on disposing found here:

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

and on list parnet web objects

http://solutionizing.net/2009/01/09/splist-parentweb-leaks-revisited/

as for the spcontext robert is correct, but not fully ;) there are some methods that you have to dispose of or use the using statment to dispose of it!

I have gone into detail on:

SPContext.Current.Site.OpenWeb()

That above is the exception to disposing of the object as it creates a new object from the current context ;)

What is the difference between SPContext.Current.Web and SPContext.Current.Site.OpenWeb()?

EDIT

to clarify on your example:

SPContext.Current.Web.ParentWeb.ParentWeb

again the above handles the idisposable and you dont need to explicitly call the dispose method! like i said above it needs to be within using statment of a web object or site object! if you explicitly dispose of the object your getting rid of the current parent parent object which will throw exceptions!

Good

using (SPWeb web = SPContext.Current.Site.OpenWeb())
{
    SPWeb parentWeb = SPContext.Current.Web.ParentWeb.ParentWeb; //No explicit dispose required
}

Bad

SPWeb parentWeb = SPContext.Current.Web.ParentWeb.ParentWeb;

the above is showing your creating a new spweb object that needs disposing because your using the current context openweb which creates a new web object but using the current context. within the using you can then call the recursive call to parent web as its handled by sharepoint regardless of the recursive calls made by ParentWeb as its already handled within the using statment! if you did call dispose than to what even parentweb you have disposed it will not only dispose of that object but also its children webs!

more on what im talking about and a solution to resources on openwebs that rely on currentcontext can be found here:

http://solutionizing.net/2009/03/19/introducing-spweb-getparentweb/

share|improve this answer
    
So if I call SPContext.Current.Web.ParentWeb.ParentWeb there is no need to dispose any of the parent webs because SharePoint handles it as part of the context dispose? This does not seem to conform with what my decompiler efforts revealed. –  Thomas Dec 6 '13 at 9:31
    
just ammended my answer –  ali Sharepoint Dec 6 '13 at 9:53
    
Ah, I see... The situation where others use the ParentWeb was one I did not consider. I think your extension method should do the trick nicely for my use. Thanks a bunch! –  Thomas Dec 6 '13 at 10:35
    
no problem happy to help! –  ali Sharepoint Dec 6 '13 at 10:39

You should never dispose a context SPWeb, or SPSite,

In your scenario above you are using the same Site object, which SharePoint do open in the background when you do new SPWeb. So by calling Dispose() on SPWeb you should be fine.

If you create an SPWeb by calling SPSite.OpenWeb() you should dispose both the SPSite and the SPWeb.

share|improve this answer
    
Hi and thanks for your reply. I updated my question to hopefully clarify a few things. I'm specifically interested in whether or not I should dispose ParentWeb or RootWeb when the context web is a sub web one or more levels below the root. The documentation seems to indicate that I shouldn't, but it doesn't deal with recursive calls to ParentWeb which has me confused. –  Thomas Dec 6 '13 at 8:07
    
As you see, the ParentWeb, and RootWeb, and Site are just properties on the objects, not actual methods. So te disposal should be handled just fine by SharePoint. You could do some testing though, executing these lines of code, and look in the ULS for messages regarding undisposed webs (to give you ease of mind) :) –  Robert Lindgren Dec 6 '13 at 8:13
    
I seem to recall the properties on certain SP objects automatically recreating new webs and sites on the fly though which caused me to wonder whether new webs where being constructed when I called ParentWeb. I'll do some testing, but I was hoping there was some official documentation on the matter. –  Thomas Dec 6 '13 at 8:17
    
I think you have already found all the offical information there is I'm afraid. And yes, there are some hidious objects, like the SPLimitedWebPartManager, that initiates a new web in it's properties –  Robert Lindgren Dec 6 '13 at 8:20
    
Love working with SharePoint ;) Thanks for the help. Some quick local tests did not reveal any dispose related log messages so for now I'm guessing no disposing is necessary. –  Thomas Dec 6 '13 at 8:23

So after doing some checking and testing I've discovered the following:

SPWeb.ParentWeb

Internally this method can construct a new web (using this.Site.OpenWeb()). It has an internal cache that will either be null if web root web or ParentWeb has never been called or an SPWeb. It would seem that a new web is opened when you call ParentWeb.

When SPWeb.Dispose is called it goes to another method called Close with appears to dispose an object of type SPWeb called m_FirstUniqueAncestorWeb. This is not the ParentWeb however, but something related to SPSecurableObject. It does not appear to automatically dispose of ParentWeb.

SPSite dispose, on the other hand, automatically closes all open webs. This would indicate that any web I open would be automatically disposed once the site is disposed (conforms to what I expected). For context site this would mean automatic disposing of all opened webs so there is technically no need to dispose of opened webs. However having a bunch of open webs within the context of one request will consume resources so I should still dispose of any new webs I open.

The ULS log did not report any dispose issues after testing for about 30 minutes. This seems to indicate that at least SharePoint does not see the relatively few parent webs I open as an issue (if that is indeed what is happening).

I'm not sure I'm able to conclude anything from all this. It would seem that the most resource friendly way to do this would be to dispose of each internal parent web in the tree. Not the leaf which would be the context web and not the root because that would be disposed automatically when the site is disposed. A dirtier way to do it would be to simply leave them open and let SharePoint dispose them when the context is disposed. Since this behaviour did not cause any warnings in the log about dispose issues it would seem to be safe though it doesn't "seem right".

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.