InstructionsThe first thing you’ll want to do is increase the maximum web parts per zone. The default is set to 50, but you can increase it by editing your web.config.
<WebPartLimits MaxZoneParts="100" PropertySize="1048576" />
You can then create a C# Console Application in Visual Studio, add a reference to Microsoft.SharePoint, and then add the following code to Program.cs. This will work with SharePoint 2007 and 2010 as long as you reference the correct assembly. Don’t forget to make sure your Visual Studio project’s Platform Target is Any CPU or x64.
Updated 6/7/2010
- Better exception handling.
- Option to delete existing web parts before adding.
- Link to Web Part Page Maintenance.
The Web Analytics Web Part and Date Filter web parts can be added manually, but have bugs that won’t allow them to be added programmatically. See comments in source code. The Excel Web Access web part is also the only one that did not have a Web Part Title by default. This is why I ended up using the Web Parts gallery list title instead. Hopefully these will be addressed with an later update.
One other thing I noticed is that sometimes the code will not add all web parts. This usually happens when I have run the code too many times in a row and my guess is a timer job is getting caught up or something is being cached. If you are on a slower environment, you may want to consider adding a few sleep statements between each web part added.
As far as results are concerned, when I create a site collection using the Publishing Portal site template and enable every site collection and site feature, I see 75 web parts total. Other than the Web Analytics and Date Filter web parts, I have seen everything else successfully added to the page.
Screenshots
Console Application – Note: I did find errors with the Web Analytics and Date Filter web parts
SharePoint Page – Notice how large that vertical scrollbar is.
Keep in mind that you can easily delete any web parts, by going to the Web Part Page Maintenance page. Simply append the query string ?contents=1 to the page URL.
Source Code:
using System; using System.Collections.Generic; using System.IO; using System.Web.UI.WebControls.WebParts; using System.Xml; using Microsoft.SharePoint; using Microsoft.SharePoint.WebPartPages; namespace AddAllWebParts { class Program { static void Main(string[] args) { AddAllWebParts("http://spdev/sites/publishingportal/SitePages/Home.aspx", true); } public static void AddAllWebParts(string pageUrl, bool deleteExisting) { int wpInstalledTotal = 0; int wpTotal = 0; string webPartTag = "<WebPartPages:WebPartZone"; try { using (SPSite site = new SPSite(pageUrl)) { using (SPWeb web = site.OpenWeb()) { using (SPLimitedWebPartManager wpMgr = web.GetLimitedWebPartManager(pageUrl, PersonalizationScope.Shared)) { if (deleteExisting) { try { List<System.Web.UI.WebControls.WebParts.WebPart> pageWps = new List<System.Web.UI.WebControls.WebParts.WebPart>(); foreach (System.Web.UI.WebControls.WebParts.WebPart wp in wpMgr.WebParts) { pageWps.Add(wp); } foreach (System.Web.UI.WebControls.WebParts.WebPart wp in pageWps) { Console.WriteLine(string.Format("Deleting Web Part: {0}", wp.Title)); wpMgr.DeleteWebPart(wp); web.Update(); } } catch (Exception ex) { Console.WriteLine("Error Deleting Existing Web Parts" + ex.Message); } } web.GetCatalog(SPListTemplateType.WebPartCatalog); SPList wpList = web.GetCatalog(SPListTemplateType.WebPartCatalog); SPFile file = web.GetFile(pageUrl); string zoneId = string.Empty; string sourceCode = System.Text.Encoding.UTF8.GetString(file.OpenBinary()); if (sourceCode.IndexOf(webPartTag) > -1) { zoneId = sourceCode.Substring(sourceCode.IndexOf(webPartTag)); if (zoneId.IndexOf("ID=") > -1) { zoneId = zoneId.Substring(zoneId.IndexOf("ID=")).Replace("ID=\"", ""); zoneId = zoneId.Substring(0, zoneId.IndexOf("\"")); } } if (!string.IsNullOrEmpty(zoneId)) { List<SPListItem> wpItems = new List<SPListItem>(); wpTotal = wpList.Items.Count; foreach (SPListItem item in wpList.Items) { wpItems.Add(item); } wpItems.Sort((x1, x2) => x1.Title.CompareTo(x2.Title)); wpItems.Reverse(); foreach (SPListItem item in wpItems) { try { string fileName = string.Format("{0}/{1}", item.Web.Url, item.File.Url); XmlTextReader reader = new XmlTextReader(new StringReader(item.Web.GetFileAsString(fileName))); string error; System.Web.UI.WebControls.WebParts.WebPart wp = wpMgr.ImportWebPart(reader, out error); if (string.IsNullOrEmpty(error)) { Console.WriteLine(string.Format("Adding Web Part: {0}", item.Title)); switch (item.Title) { case "Date Filter": //TODO: Date Filter has a TargetInvocationException. Not sure why this fails. break; case "Web Analytics Web Part": //TODO: Web Analytics Web Part fails with an XML. //I have validated the dwp and even removed comments to no avail. //http://social.technet.microsoft.com/Forums/en-CA/sharepoint2010programming/thread/f2f7684d-58a7-4fb4-94a4-199ba4132a53 break; } wpMgr.AddWebPart(wp, zoneId, Convert.ToInt32(0)); wpMgr.SaveChanges(wp); web.Update(); wpInstalledTotal++; } else { Console.WriteLine(string.Format("Error Adding Web Part: {0} {1})", item.Title, error)); } } catch (Exception ex) { Console.WriteLine(string.Format("Error Adding Web Part: {0} {1})", item.Title, ex.Message)); } } Console.WriteLine("Adding Content Editor Web Part with Web Part Page Maintenance Link"); ContentEditorWebPart contentEditor = new ContentEditorWebPart(); contentEditor.ZoneID = zoneId; contentEditor.ChromeType = PartChromeType.None; XmlDocument xmlDoc = new XmlDocument(); XmlElement xmlElement = xmlDoc.CreateElement("p"); xmlElement.InnerText = "<h3><a href='" + pageUrl + "?contents=1'>Web Part Page Maintenance</a></h3>"; contentEditor.Content = xmlElement; contentEditor.Content.InnerText = xmlElement.InnerText; wpMgr.AddWebPart(contentEditor, contentEditor.ZoneID, 0); wpMgr.SaveChanges(contentEditor); web.Update(); } else { Console.WriteLine("The page contains no web part zones."); } } } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.WriteLine(string.Format("Total Web Parts Added: {0} of {1}", wpInstalledTotal.ToString(), wpTotal.ToString())); Console.Read(); } } }
Very nice information shared by you. I was just searching this type of information and luckily I got it from your blog. I like your blog also. Keep it up.
ReplyDeleteThis should be useful enough to have it inside my system.
ReplyDeleteLengthy but very gud information from your side :)
ReplyDeleteapparently DateFilterWebPart cannot be added without a context. you can fake a context and it will work
ReplyDelete#fake context - the SPWeb object passed to the SetContextWeb method must be created using the SPSite.OpenWeb() method
$site = New-Object Microsoft.SharePoint.SPSite($webUrl)
$web = $site.OpenWeb()
[System.Web.HttpRequest] $request = New-Object System.Web.HttpRequest("", $web.Url, "")
$sw = New-Object System.IO.StringWriter
$hr = New-Object System.Web.HttpResponse($sw)
[System.Web.HttpContext]::Current = New-Object System.Web.HttpContext($request, $hr)
[Microsoft.SharePoint.WebControls.SPControl]::SetContextWeb([System.Web.HttpContext]::Current, $web)
#do stuff
[System.Web.HttpContext]::Current = $null