Moving up to find that list
I'm going to write a bit about a problem I ran into when I wrote a bulk upload application for one of my SharePoint clients. I found that when I was importing a document and applying a Content Type to it I needed to find the Lookup list values for one of the import fields. In looking for a list of lookup values I started with this code:
public static SPList GetListByName(SPWeb web, string listName)
{
SPList retVal = null;
foreach (SPList list in web.Lists)
{
if (list.Title.ToLower().Equals(listName.ToLower()))
{
retVal = list;
}
}
return retVal;
}
That is, I passed in the current web and the list name that I was looking for and iterated the lists in the web looking for a name match. That code quickly became this code:
public static SPList GetListByName(SPWeb web, string listName)
{
return web.Lists[listName.ToLower()];
}
In this code I let the object's enumerator handle the iteration for me. So quick and easy and I'm done - but not so fast. The only problem was that it didn't work. The first time I looked for a Lookup Column that wasn't in the current web an Exception was thrown. Almost as soon as I started importing I needed a Lookup Column that was a site column and the document was being uploaded into the Documents folder in a sub-site, in this particular case, two sites down from the root.
Once I realized that the List existed but in a different context than that in which I was looking, I figured all I would need to do was get to the root and start looking using recursion, but instead of starting at the top and searching down, I thought that starting from where I was and moving up was a better approach. In the instance where the List is in the parent web it is easier and faster to move up using web.ParentWeb from where you are, rather than iterating down through all of the child webs using web.Webs from the root. That got me to this point:
public static SPList GetListByName(SPWeb web, string listName)
{
SPList retVal = web.Lists[listName.ToLower()];
if (retVal == null) // recurse up
{
if (web.ParentWeb != null)
{
retVal = GetListByName(web.ParentWeb, listName);
}
}
return retVal;
}
But as you can see I forgot about the Exception being thrown, so I put the recursive call into a catch block and ended up with this code:
public static SPList GetListByName(SPWeb web, string listName)
{
try
{
SPList retVal = web.Lists[listName.ToLower()];
}
catch
{
if (retVal == null) // recurse up
{
if (web.ParentWeb != null)
{
retVal = GetListByName(web.ParentWeb, listName);
}
}
}
return retVal;
}
This approach was the one that finally worked. If it didn't find the list by name in the current lists for the web it would throw an Exception and the catch block would then check to make sure that the retVal was still null, on the chance that the exception was thrown after it was set. If it was null, it looked to see if the current web had a parent web and if so used that web to recursively call the method. The two base cases in this recursion are:
- 1. The code in the try block does not throw an error, in which case the list was found, or
- 2. The web.ParentWeb is null, which means we are at the root of the site and the list does not exist.
That wraps it up for this time, hope it made your life a little easier.