Duke SiteWalker
I find that in almost every SharePoint tool I’m writing these days I have to traverse the webs in a site collection, thus, I tend to duplicate the following logic.
- Get an SPSite of the site collection
- Start at SPSite.RootWeb,
- Do something with the Web
- Enumerate the SPWeb.Webs collection of subwebs
- Do something with the folders in the web
- Do something with the lists in the web
- For this web, repeat step 4 for each subweb.
- Etc.
Well, I’m tired of duplicating code, so I took the time this morning to write a Site Walker that uses Delegates to call back to the apps “DoSomething” methods.
First, here’s the meat of the SiteWalker class, and then a small application using it called DukeSiteWalkerl;
SiteWalker.cs
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace SPSiteWalker
{
class SiteWalker
{
public delegate bool SPSiteCollectionDelegate(SPSiteCollection sc, object o);
public delegate bool SPSiteDelegate(SPSite site, object o);
public delegate bool SPWebDelegate(SPWeb web, object o);
public delegate bool SPFolderDelegate(SPFolder folder, object o);
public delegate bool SPListDelegate(SPList list, object o);
public SPSiteCollectionDelegate m_SiteCollectionDelegate = null;
public SPSiteDelegate m_SiteDelegate = null;
public SPWebDelegate m_WebDelegate = null;
public SPFolderDelegate m_FolderDelegate = null;
public SPListDelegate m_ListDelegate = null;
public bool WalkSiteCollection(SPSiteCollection sc, object o)
{
m_SiteCollectionDelegate(sc,o);
foreach(string strSite in sc.Names)
{
string strURL = sc.VirtualServer.Url.ToString() + strSite;
SPSite site = new SPSite(strURL);
m_SiteDelegate(site,o);
WalkSite(site,o);
site.Close();
}
return true;
}
public bool WalkSite(SPSite site, object o)
{
m_SiteDelegate(site,o);
WalkWeb(site.RootWeb,true, o);
return true;
}
public bool WalkWeb(SPWeb web, bool bRecurseWebs, object o)
{
try
{
m_WebDelegate(web,o);
foreach(SPList list in web.Lists)
{
WalkList(list,o);
}
foreach(SPFolder folder in web.Folders)
{
WalkFolder(folder,true,o);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
// do the same for all subwebs
if(bRecurseWebs)
{
foreach(SPWeb subweb in web.Webs)
{
WalkWeb(subweb,true,o);
}
}
return true;
}
public bool WalkFolder(SPFolder folder,bool bRecurseFolders, object o)
{
try
{
m_FolderDelegate(folder,o);
if(bRecurseFolders)
{
foreach(SPFolder subfolder in folder.SubFolders)
WalkFolder(subfolder,true,o);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
return true;
}
public bool WalkList(SPList list, object o)
{
// List Stuff
m_ListDelegate(list,o);
return true;
}
}
}
As you can see, we simply “Walk” over all the sites/webs/subwebs and call the associated delegate to perform “Application Specific” actions on them.
Here is the example application DukeSiteWalker.cs that utilizes the SiteWalker.
DukeSiteWalker.cs
using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using SPSiteWalker;
namespace DukeSiteWalker
{
class AppClass
{
[STAThread]
static void Main(string[] args)
{
SiteWalker walker = new SiteWalker();
walker.m_SiteCollectionDelegate = new SPSiteWalker.SiteWalker.SPSiteCollectionDelegate(AppClass.MySiteCollectionMethod);
walker.m_SiteDelegate = new SiteWalker.SPSiteDelegate(AppClass.MySiteMethod);
walker.m_WebDelegate = new SiteWalker.SPWebDelegate(AppClass.MyWebMethod);
walker.m_FolderDelegate = new SiteWalker.SPFolderDelegate(AppClass.MyFolderMethod);
walker.m_ListDelegate = new SiteWalker.SPListDelegate(AppClass.MyListMethod);
SPGlobalAdmin gAdmin = new SPGlobalAdmin();
foreach(SPVirtualServer vs in gAdmin.VirtualServers)
{
if(vs.State == SPVirtualServerState.Ready)
walker.WalkSiteCollection(vs.Sites,System.Console.Out);
}
//
// If I wanted to just walk a single site collection
//
// SPSite site = new SPSite("https://localhost");
// walker.WalkSite(site,System.Console.Out);
// site.Close();
// site.Dispose();
}
private static bool MySiteCollectionMethod(SPSiteCollection sc,object o)
{
System.IO.TextWriter writer = (System.IO.TextWriter)o;
writer.WriteLine("In MySiteCollectionMethod for site collection with " + sc.Count + " sites");
return true;
}
private static bool MySiteMethod(SPSite site,object o)
{
System.IO.TextWriter writer = (System.IO.TextWriter)o;
writer.WriteLine("In MySiteMethod for site " + site.ServerRelativeUrl);
return true;
}
private static bool MyWebMethod(SPWeb web,object o)
{
System.IO.TextWriter writer = (System.IO.TextWriter)o;
writer.WriteLine("In MyWebMethod for web " + web.ServerRelativeUrl);
return true;
}
private static bool MyFolderMethod(SPFolder folder,object o)
{
System.IO.TextWriter writer = (System.IO.TextWriter)o;
writer.WriteLine("In MyFolderMethod for folder " + folder.ServerRelativeUrl);
return true;
}
private static bool MyListMethod(SPList list,object o)
{
System.IO.TextWriter writer = (System.IO.TextWriter)o;
writer.WriteLine("In MyListMethod for list " + list.DefaultViewUrl);
return true;
}
}
}
The sample app, defines call back methods (delegates) that the SiteWalker code will invoke for each of it’s respective objects. As you’ll notice, I’ve defined the delegates so that they all take a secondary base object class. This allows you to pass in a reference to an object to store your data (depending on your needs) . DukeSiteWalker simply uses this to pass in the System.Console.Out object to report back where it’s at.
My mind is racing with the possibilities on how this is going to make my life easier J I hope it makes your SharePoint development endeavors easier too.
Look for the SiteWalker class to show up in the next version of SPUserUtil, SPSiteBuilder, SPSiteManager, and other of the tools I put together on the SharePoint Utility Suite.
- Keith Richie
Comments
Anonymous
May 17, 2005
Nice idea. Never thought of using delegates to do all the heaving lifting (okay, so it's not so heavy but it is repetative) and leaving my Domain code to do the app specific stuff.Anonymous
June 02, 2005
Thanks Bil for the comment, yeah...I was driving to work and thinking about it, and went "Hey, why not use a delegate :)" I hope to find the time soon, to base all the SharePoint Utility Suite tools that need this.
Let me know if anyone sees ways to improve itAnonymous
January 21, 2009
PingBack from http://www.keyongtech.com/1992246-how-to-get-top-levelAnonymous
May 29, 2009
PingBack from http://paidsurveyshub.info/story.php?title=keith-richie-duke-sitewalker