Tuesday, October 16, 2007

Run code to make changes to all sites in a site collection - code sample

I can’t remember the number of times I had to make the slightest change on all site on the same site collection.
One more loop, one more recursive call… you know…
What am I talking about?
Ever needed to:
· Change a site’s title for all sites?
· Change the email for request access to all sites?
· Cancel request access to all sites?
· Change theme on X number of sites?
· Delete a list from all sites, add another list to all sites, and so on and so forth…
Well, all these needs have one thing in common – they can be easily done using code that iterates through all sites in a site collection.
Writing the long, repeating code that performs this iteration can be very time consuming and redundant.
Here is a code sample that will allow you to run any code you wish on all sites in a collection simple by handling the action you want on one site only. No need to iterate all sites and worry about recursive methods any more.
Simply add this code to you utilities / class code:
#region actions for all webs
delegate void RunForAllWebsAction(SPWeb web);
static void RunForAllWebs(RunForAllWebsAction action)
{
try
{
string rootUrl = GetAppConfigValue("RootWebUrl");
SPSite site = new SPSite(rootUrl);
SPWeb rootWeb = site.OpenWeb();
RunForAllWebs(rootWeb, action);
}
catch (Exception ex)
{
Console.WriteLine("** Error: " + ex.ToString());
}
}
static void RunForAllWebs(SPWeb current, RunForAllWebsAction action)
{
Console.WriteLine("* Starting action on " + current.Url);
action(current);
Console.WriteLine("* Done.");

foreach (SPWeb sub in current.Webs)
RunForAllWebs(sub, action);
}
#endregion


Now, all you need to do is create a function of this delegate:
void RunForAllWebsAction(SPWeb web);
For example to add “class number: ” to each site on the classes site collection, create this delegate only:
void ChangeTitle(SPWeb web)
{
web.Title = "class number: " + web.Title;
web.Update();
}


And you are done.
(Note that I have only added 2 lines of code to make the change I wanted…)

To make a call to run ChangeTitle on all webs call this:
RunForAllWebs(ChangeTitle);

Well, hope this helps the developers in you,
Shai Ben Shooshan.

2 comments:

Anonymous said...

I noticed you never called Dispose on any of your SPSite or SPWeb objects. This can cause problems with memory leakage and objects being stored in memory for an excessive amount of time. This is an excelent article on this subject:
http://msdn2.microsoft.com/en-us/library/aa973248.aspx#sharepointobjmodel__spsiteobjects

Shai Petel (Ben Shooshan) said...

Of course you are right.

I Should dispose / put the site in a using statement.

This is just an example code - feel free to use and update it,