views:

726

answers:

4

I have an arbitrary url. I know this url represents some path on my local SharePoint server. With the SharePoint API, I want to know if there is a site corresponding to this url. What's the best way to do this?

I thought this should work:

using (SPSite site = new SPSite(url))
{
    using (SPWeb web = site.OpenWeb())
    {
        bool exists = web.Exists;
    }
}

But this seems to return true even when the SPWeb isn't really there. For example, if I have an actual site at this url:

http://myserver/a/b

Then the above code returns true if I ask for this site, even when it's not really a provisioned site:

http://myserver/a/b/c

In this case, the reference to "web" is actually the http://myserver/a/b web site, which is not really what I wanted. What's the right way to check to see if this site is really there?

A: 

You need to grab the SPWeb associated with the top level, not spsite; here's what I use:

private bool ChildWebExists(SPWeb parentWeb, string childWebName) {   
    using (SPweb childWeb = parentWeb.Webs[childWebName]) {   
        return childWeb.Exists;   
    }   
}

edit: whoops, you're doing the same thing; strange it works like a charm for me.

Jason Watts
So having a single url is not sufficient? In my case, I don't know how deep the web tree really is. Do I need to start at the root site (I guess I do know that my site collection is at the server root), split my url into path fragments, and then walk down the tree?
Chris Farmer
I'm thinking the same thing. I always check for existance relative to the top level site collection, so you may need to walk it i'm thinking (haven't tested it however YMMV)
Jason Watts
Tried it out, seems that you can't plug in arbitrary urls, which is very strange to me (since the constructor should be returning the same spweb object, regardless of whether we "walked" there or not!)
Jason Watts
Wait Chris, just took a second look at your code, when you use the constructor for spsite (with the absolute reference to a child site), it's ALWAYS returning the top level site SPWeb object when you call opensite (spsites constructor always resolves to the spsite site collection object, regardless of the child referenced). You need to deal with SPWeb's constructor to get references
Jason Watts
Another thing I thought about was just poking at the url with HttpWebRequest and seeing if a 200 response code came back. In my case, I know that there are no other non-SharePoint sites on my server, so I think this might be safe.
Chris Farmer
I agree that I seem to be misusing the SPSite.OpenWeb method here, but it *DOES* work for sites that are actually there. I guess that gave me a false sense of security.
Chris Farmer
SharePoint's OM definately has some funny idiosyncrasies. You beat me to my next recommendation; which was to webrequest arbitrary urls for a response. That could be a decent stopgap for now i'd think, until something gets figured out. I'd stay and help, but it's friday and I have some drinking to attend to; have a great weekend, and good luck!
Jason Watts
A: 

I'm pretty sure I've had mixed results using SPSite(url) and then using site.OpenWeb() which is why I don't try that any more. Assuming your site collection is at http://myserver/a/b, have you tried:

using (SPSite site = new SPSite("http://myserver/a/b"))
using (SPWeb web = site.OpenWeb("/c"))
{
  return web.Exists;
}

I'd try using Reflector but the useful methods are obfuscated.

Alex Angas
A: 

Sometimes the tricky part is to figure out the URL portion that makes up the SPSite's URL and the relative SPWeb's URL.

Here's some code that works just by taking the full URL (comments welcome, there's always a bug lying around ☺):

    private static bool ExistsWeb(string fullUrl)
    {
        using (SPSite s = new SPSite(fullUrl))
        {
            string webSiteRelUrl = GetWebSiteRelativeUrl(fullUrl, s);
            using (SPWeb w = s.OpenWeb(webSiteRelUrl))
            {
                return (w.Exists);
            }
        }
    }

    private static string GetWebSiteRelativeUrl(string fullUrl, SPSite s)
    {
        string webSiteRelUrl = fullUrl.Replace(s.Url, string.Empty);
        if (webSiteRelUrl.Length >= 1 && webSiteRelUrl[0] == '/')
        {
            if (webSiteRelUrl.Length == 1)
            {
                webSiteRelUrl = string.Empty;
            }
            else
            {
                webSiteRelUrl = webSiteRelUrl.Substring(1);
            }
        }
        return webSiteRelUrl;
    }
Ariel
+1  A: 

I think you could use the standard OpenWeb method. I have described the issue on my blog @ http://blog.mastykarz.nl/inconvenient-opening-spsite-openweb/. While I needed to get the first existing web, you would need to check if there is a site at the exact URL. By using the (string, bool) overload and passing true as the second parameter you should get the job done.

Waldek Mastykarz - MOSS MVP