sharepointidisposableusingspweb

Using disposed SPSite and SPWeb objects


I was happy enough to have inherited a terribly written SharePoint project.
Apparently, the original developer was a big fan of reusable code (30% of code is reused across 20 projects without using any libraries—guess how?).

I would often find his code calling some Common.OpenWeb method to retrieve SPWeb object for operating SharePoint stuff. Most of this function's incarnations look exactly the same:

public SPWeb OpenWeb()
{
    String strSiteUrl = ConfigurationManager.AppSettings["SiteUrl"].ToString();
    SPSite site = null;
    SPWeb web = null;
    try
    {
        using (site = new SPSite(strSiteUrl))
        {
            using (web = site.OpenWeb())
            {
                return web;
            }
        }
    }
    catch (Exception ex)
    {
        LogEvent("Error occured in OpenWeb : " + ex.Message, EventLogEntryType.Error);
    }
    return web;
}

And now I'm really worried.
How come this works in production? This method always returns a disposed object, right?

How unstable is it, exactly?

UPDATE:

This method is used in the following fashion:

oWeb = objCommon.OpenWeb();
SPList list = oWeb.Lists["List name"];
SPListItem itemToAdd = list.Items.Add();
itemToAdd["Some field"] = "Some value";
oWeb.AllowUnsafeUpdates = true;
itemToAdd.Update();
oWeb.AllowUnsafeUpdates = false;

I omitted the swallowing try-catch for brevity.
This code inserts value into the list! This is a write operation, I'm pretty sure Request property is being used for this. Then how can it work?


Solution

  • First, the short answer: that method indeed returns a disposed object. An object should not be used after being disposed, because it's no longer in a reliable state, and any further operation performed on that object should (theoretically) throw an ObjectDisposedException.

    Now, after digging a little, SharePoint objects don't seem to follow that rule. Not only does SPWeb never throw ObjectDisposedException after being disposed, but it actually tests for that case in its Request property and rebuilds a valid SPRequest from its internal state if it has been disposed.

    It seems that at least SPWeb was designed to be fully functional even in a disposed state. Why, I don't know. Maybe it's for accommodating client code like the one you're working on. Maybe it's some kind of complicated optimization I can't possibly understand.

    That said, I'd suggest you don't rely on that behavior, because it might change in the future (even though, given Microsoft's policy on bug-for-bug backwards compatibility, it might not).

    And of course, you will still leak the new SPRequest instance, which can be quite costly. Never, ever, use a disposed object, even if SharePoint lets you get away with it.