The possibility to add web parts in rich content on publishing pages in SharePoint 2013 offer exciting opportunities to SharePoint administrators and editors. It enables us to work with our content in a much more integrated way, combining static page content with more dynamic web parts. It will allow us to focus on the content and increase the user experience.

It will allow us to focus on the content and increase the user experience.In earlier versions of SharePoint, were we didn’t have this possibility, we as developer often found ourselves in an uneven battle. We either had to spend quite some time building a whole bunch of page layouts with a maze of content fields and web part zones or cause frustration among our editors for not providing them with the tools they needed. With the possibility to add web parts in rich content we can put together a few rather simple page layouts and still give the editors a more flexible set of tools than before.

About a week ago I wrote a blog post about adding web parts using PowerShell. I would now like to show you how to modify that PowerShell script to allow us to add the web part inside a rich content field instead of in a traditional web part zone.

How does it work?

The technical concept behind adding a web part in rich content in SharePoint 2013 is almost the same as for wiki-pages in SharePoint 2010.

First, we don’t add the actual web part inside the rich content filed. Instead we add the web part in a hidden web part zone named wpz. By hidden I mean that this web part zone is not displayed for the users on the page.

Secondly, we add a web part placeholder, a HTML snippet, to the rich content field. The placeholder reference the web part using the web part’s unique ID. You are able to see this snippet in plain text if you add a web part to one of your rich content fields using the web interface and then choose ”Edit source” in the ribbon to see the HTML code.

SharePoint takes care of the rest and make sure the web part in the hidden web part zone is displayed in the rich content field when the page is rendered.

The script

The script for adding a web part to a rich content field is similar to adding the web part to a traditional web part zone. The main difference is that we will add the web part to the hidden wpz zone and at the same time add the placeholder to the rich content field. We will also have to generate a unique ID for the web part in order to be able to set the reference to the web part in the HTML snippet inside the rich content.

$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null) { Add-PSSnapin "Microsoft.SharePoint.Powershell" }
 
$SiteUrl = "http://portal.devserver.local/"
$WebUrl = "http://portal.devserver.local/testweb"
$PageLayoutRelUrl = "/_catalogs/masterpage/PageFromDocLayout.aspx"
$PageName = "MyPage.aspx"
$PageTitle = "My Page"
$WebPartFileName = "SummaryLinks.webpart"
$WebPartZoneIndex = 1
 
$Site = Get-SPSite($SiteUrl)
$PubSite = New-Object Microsoft.SharePoint.Publishing.PublishingSite($Site)
$Web = Get-SPWeb $WebUrl
$PubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($Web)
 
$Layouts = $PubSite.GetPageLayouts($False)
$PageLayout = $Layouts[$PageLayoutRelUrl]
 
# Add a new publishing page.
$Page = $PubWeb.AddPublishingPage($PageName, $PageLayout)
$Page.Title = $PageTitle
$Page.Update();
 
$WPMgr = $Web.GetLimitedWebPartManager("Pages/$PageName", [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)
 
# Generate a storage key/web part ID.
$StorageKey = [guid]::NewGuid().ToString()
$WPID = 'g_' + $StorageKey.Replace('-','_')
 
# Import and add the web part to the wpz web part zone.
$Dir = resolve-path .\
$WebPartFilePath = join-path -path $Dir -childpath $WebPartFileName
$WebPartXml = get-content $WebPartFilePath
$SR = New-Object System.IO.StringReader($WebPartXml.OuterXml)
$XTR = New-Object System.Xml.XmlTextReader($SR)
$Err = $null
$WP = $WPMgr.ImportWebPart($XTR, [ref] $Err)
$WP.ID = $WPID
$WPMgr.AddWebPart($WP, "wpz", 1)
 
# Generate the HTML code for the rich content field.
$Content = '<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false"><div class="ms-rtestate-notify  ms-rtestate-read {0}" id="div_{0}" unselectable="on"></div><div id="vid_{0}" unselectable="on" style="display: none;"></div></div>' -f $StorageKey.ToString()
 
# Add the content to the rich content field.
$Page.ListItem["PublishingPageContent"] = $Content
$PublishingPage.ListItem.Update()
 
# Check in and publish the new page. 
$Page.CheckIn("")
$Page.ListItem.File.Publish("")

The result should be exactly the same as if you would add the web part in the rich content field using the web interface. However, using PowerShell you will be able to replicate the process two or why not a 1000 times with exactly the same result.