The Danger in using SPSite.OpenWeb()

Recently I ran into a “feature” of SharePoint’s SPSite.OpenWeb() method (the no argument constructor specifically). If the OpenWeb() method is used with a URL that is not known to exist, it can result in some unexpected behavior.

Assuming you have the following site structure…

  • SiteCollection
    • Subsite1
    • Subsite2

Can you find the bug?

1
2
3
4
5
6
7
8
9
10
11
12
// !!! warning !!!
// !!! dangerous code ahead !!!
string server = "http://myserver";
string siteUrl = "/sites/SiteCollection/This Subsite Does Not Exist";
using (SPSite site = new SPSite(server + siteUrl))
{
    using (SPWeb web = site.OpenWeb())
    {
        Console.WriteLine(site.Url);
        Console.WriteLine(web.Url);
    }
}

The problem reveals itself when the URL’s are printed. Output:

http://myserver/sites/SiteCollection
http://myserver/sites/SiteCollection

The URL for the SPWeb that was just opened is the same as the SPSite’s URL: http://myserver/sites/SiteCollection. There is no exception thrown.

The behavior I expected, would be some sort of exception when opening a web that does not exist. Even worse is the fact that no error is thrown; it simply defaults to the top level site collection that exists. This means, you get the wrong SPWeb object. This error can happen when you use the no argument OpenWeb method call.

A better way to get an SPWeb object passes an argument to OpenWeb (updated 7/13/09 per Rikard’s comment):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// better code to open a web
string server = "http://myserver";
string siteUrl = "/sites/SiteCollection";
string subSite = "This Subsite Does Not Exist";
using (SPSite site = new SPSite(server + siteUrl))
{
    using (SPWeb web = site.OpenWeb(subSite))
    {
        if (web.Exists)
        {
            // do work with the web...
            Console.WriteLine(site.Url);
            Console.WriteLine(web.Url);
        }
    }
}

This code should be able to safely open a web at any location.  Keep in mind, trying to access any of the properties of a web that does not exist will result in:

System.IO.FileNotFoundException: There is no Web named “/sites/SiteCollection”.

Again, the exception is not thrown in the constructor, but when attempting to access the SPWeb’s properties… such as web.Url.