views:

47

answers:

3

Hello.

I have a list of urls (content type usage url's). Now, content types are deployed across web's. I need to loop those content types and do some actions in each list, but opening new SPWeb instance every loop is too resource intensive.

Is there built-in method to tell me if this URL belongs to certain SPWeb object?

Example:

SPWeb's may be

With content type usage links like:

  • /web2/Pages
  • /web2/Lists/Tasks
  • /web2/Lists/Documents
  • /web2/subweb1/Lists/Tasks
  • ...

As you can see, for first 3 usages i don't need to open up new SPWeb

A: 

Hi.

As far as I know, there is no built-in method for this kind of thing.
I would suggest that you create an SPWeb extension method for this.

Here's a code snippet to get you started (not tested 100%):

public static class SPWebExtensions
{
  public static bool UrlBelongsToweb(this SPWeb web, string url)
  {
    Uri uriWeb = new Uri(web.Url);

    if (uriWeb.LocalPath.ToLower() == url.ToLower())
      return true;

    if (!url.ToLower().StartsWith(uriWeb.LocalPath.ToLower()))
      return false;

    foreach (SPWeb subWeb in web.Webs)
    {
      Uri uriSub = new Uri(subWeb.Url);
      if (url.ToLower().StartsWith(uriSub.LocalPath.ToLower()))
        return false;

      subWeb.Dispose();
    }
    return true;
  }
}

You would use it in something like this:

 bool urlBelongsToWeb = web.UrlBelongsToweb("/web2/Lists/Documents");

Where web is your current SPWeb object.

Alternatively, if you want to target specific Lists in your SiteCollection, use the SPSiteDataQuery to get hold of them and do your magic work against them.

Magnus Johansson
Thanks for the snippet.But this won't be good for me, because it involves looping throught subwebs which is a big performance hit. And all i want to know is - should i open new SPWeb or not? Method involes opening new SPWeb many more times. By the way, before someone copies method, dipose subWeb appropriately in finally block.
Janis Veinbergs
@Janis. Thanks for the catch, code updated.
Magnus Johansson
@Janis. How about SPSiteDataQuery to get the lists in question? Or, if performance is your concern, query the SiteMap to determine if the test Urls are Webs or Lists. Is this a repetitive task, or a one-shot?
Magnus Johansson
It's a one shot (on feature activation). Ehh, sorry, I shouldn't care too much weather it takes 1 second or maybe 5 seconds. It adds too much complexity. Just wanted to find out maybe there is a builtin function for that.
Janis Veinbergs
+1  A: 

What context will your code be running in?

What I mean is, it looks like you want to write some code that will be run as part of a deployment process, meaning that its only going to be run occasionally.

If that is the case, does it matter whether or not your code is optimized for performance? In my opinion, it might be better to stick with a simple solution of opening up each SPWeb and not worry too much about the performance.

If you need to loop over hundreds or thousands of sites, its going to take some time. Whether your code takes ten minutes to do this, or fifteen, shouldn't really matter.

Performance would be more of an issue if this was going to be run many times, and often.

Paul Lucas
Yes, it is for deployment process. Sorry, in this case it looks like it does not matter, you're right.
Janis Veinbergs
+1  A: 

Just a guess, but maybe it's worth trying SPWeb.GetList(serverRelativeUrl) on the SPWeb instanes you already have and, if none matches, then create a new SPWeb?

Update: another idea. Assuming that all the SPWebs live in the same SPSite, you might as well use this particular overload of SPSite.OpenWeb() (and set the requestExactUrl flag to false). This will return you the SPWeb object you need. Internally, the opened SPWeb objects are reused (which you can see in SPWeb.SPWebConstructor method in Reflector), so this won't hit performance too much. wrong, the SPweb objects are just stored in a list, not reused.

naivists
I think this is a simple solution - try with GetList method, if unsucessfull, then i`ll use OpenWeb().Thank you.
Janis Veinbergs