Provisioning page with configured web part from Visual Studio

It is very convenient and very elegant solution to create and deploy page using wsp. Manual steps to create page and then add web part manually or through powershell scripts sometimes are overhead for SharePoint administrator.

1. Create a page in SharePoint. Manually add a web part. In this case I am adding a SharePoint out of the box content editor web part. 

2. Configure the web part and then export it. Once you have the dwp file open and copy the content enclosed with <WebPart> tag

e.g.

<?xml version="1.0" encoding="utf-8"?> <WebPart xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/WebPart/v2"> <Title>Access Denied</Title> <FrameType>Default</FrameType> <Description>Allows authors to enter rich text content.</Description> <IsIncluded>true</IsIncluded> <ZoneID>MainZone</ZoneID> <PartOrder>0</PartOrder> <FrameState>Normal</FrameState> <Height /> <Width /> <AllowRemove>true</AllowRemove> <AllowZoneChange>true</AllowZoneChange> <AllowMinimize>true</AllowMinimize> <AllowConnect>true</AllowConnect> <AllowEdit>true</AllowEdit> <AllowHide>true</AllowHide> <IsVisible>true</IsVisible> <DetailLink /> <HelpLink /> <HelpMode>Modeless</HelpMode> <Dir>Default</Dir> <PartImageSmall /> <MissingAssembly>Cannot import this Web Part.</MissingAssembly> <PartImageLarge>/_layouts/15/images/mscontl.gif</PartImageLarge> <IsIncludedFilter /> <Assembly>Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly> <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName> <ContentLink xmlns="https://schemas.microsoft.com/WebPart/v2/ContentEditor" /> <Content xmlns="https://schemas.microsoft.com/WebPart/v2/ContentEditor"><![CDATA[​Access Denied.&#160; Please contact Administrator.]]></Content> <PartStorage xmlns="https://schemas.microsoft.com/WebPart/v2/ContentEditor" /> </WebPart>

3. Also download the new page you just created in SharePoint. You will get something like below.

<%@ Page Inherits="Microsoft.SharePoint.Publishing.TemplateRedirectionPage,Microsoft.SharePoint.Publishing,Version=15.0.0.0, Culture=neutral,PublicKeyToken=71e9bce111e9429c" %> <%@ Reference VirtualPath="~TemplatePageUrl" %> <%@ Reference VirtualPath="~masterurl/custom.master" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"><head> <!--[if gte mso 9]><SharePoint:CTFieldRefs runat=server Prefix="mso:" FieldList="FileLeafRef,Comments,PublishingStartDate,PublishingExpirationDate,PublishingContactEmail, PublishingContactName,PublishingContactPicture,PublishingPageLayout,PublishingVariationGroupID, PublishingVariationRelationshipLinkFieldID, PublishingRollupImage,Audience,PublishingIsFurlPage,SeoBrowserTitle,SeoMetaDescription, SeoKeywords,RobotsNoIndex,eRebEntity"><xml> <mso:CustomDocumentProperties> <mso:PublishingContact msdt:dt="string">1073741823</mso:PublishingContact> <mso:PublishingIsFurlPage msdt:dt="string">0</mso:PublishingIsFurlPage> <mso:display_urn_x003a_schemas-microsoft-com_x003a_office_x003a_office_x0023_PublishingContact msdt:dt="string">System Account</mso:display_urn_x003a_schemas-microsoft-com_x003a_office_x003a_office_x0023_PublishingContact> <mso:PublishingContactPicture msdt:dt="string"></mso:PublishingContactPicture> <mso:RobotsNoIndex msdt:dt="string">0</mso:RobotsNoIndex> <mso:PublishingContactName msdt:dt="string"></mso:PublishingContactName> <mso:ContentTypeId msdt:dt="string"> 0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900 B3313EDD2C4B4EAC9D8A2EA8C0F6CF1D00BE9190263CAA2946A1A8D14D4C5EBD43</mso:ContentTypeId> <mso:PublishingPageLayoutName msdt:dt="string">eREBStudyPage.aspx</mso:PublishingPageLayoutName> <mso:Comments msdt:dt="string"></mso:Comments> <mso:PublishingContactEmail msdt:dt="string"></mso:PublishingContactEmail> <mso:PublishingPageLayout msdt:dt="string"> https://dev.erebportal.com/_catalogs/masterpage/eREBStudyPage.aspx, /_catalogs/masterpage/eREBStudyPage.aspx </mso:PublishingPageLayout> <mso:RequiresRouting msdt:dt="string">False</mso:RequiresRouting> </mso:CustomDocumentProperties> </xml></SharePoint:CTFieldRefs><![endif]--> <title>Access Denied</title></head>

4. Now create a module in Visual Studio. Add the page file you just downloaded.

5. The elements.xml file will have an entry for the page you just added.

6. Modify the elements.xml file. 

To do this we will:

  • First add an allUsersWebPart
  • Find the <![CDATA[ section
  • Put all the code copied from the text editor of exported web part here.
  • Notice just for content editor web part as you cannot have <![CDATA[ under <![CDDATA we have to encode the html content within it. Make sure to add the default html in encoded format. You can use any online HTML encoder to encode your HTML. If you add the content in normal HTML format, SharePoint by default will remove all the HTML mark-up and will put the whole content under a single DIV element. So make sure you add the content in HTML encoded format.

7. The final elements.xml will look like this

to look like below

<File Path="Pages\AccessDenied.aspx" Url="AccessDenied.aspx" Type="GhostableInLibrary" ReplaceContent="TRUE" > <AllUsersWebPart WebPartZoneID="MainZone" ID="AccessDeniedCEWP" WebPartOrder="1"> <![CDATA[<WebPart xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://schemas.microsoft.com/WebPart/v2"> <Title>Access Denied</Title> <FrameType>Default</FrameType> <Description>Allows authors to enter rich text content.</Description> <IsIncluded>true</IsIncluded> <ZoneID>MainZone</ZoneID> <PartOrder>0</PartOrder> <FrameState>Normal</FrameState> <Height /> <Width /> <AllowRemove>true</AllowRemove> <AllowZoneChange>true</AllowZoneChange> <AllowMinimize>true</AllowMinimize> <AllowConnect>true</AllowConnect> <AllowEdit>true</AllowEdit> <AllowHide>true</AllowHide> <IsVisible>true</IsVisible> <DetailLink /> <HelpLink /> <HelpMode>Modeless</HelpMode> <Dir>Default</Dir> <PartImageSmall /> <MissingAssembly>Cannot import this Web Part.</MissingAssembly> <PartImageLarge>/_layouts/15/images/mscontl.gif</PartImageLarge> <IsIncludedFilter /> <Assembly>Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly> <TypeName>Microsoft.SharePoint.WebPartPages.ContentEditorWebPart</TypeName> <ContentLink xmlns="https://schemas.microsoft.com/WebPart/v2/ContentEditor" /> <Content xmlns="https://schemas.microsoft.com/WebPart/v2/ContentEditor">&lt;div&gt;​Access Denied.&#160; Please contact Administrator.&lt;/div&gt;</Content> <PartStorage xmlns="https://schemas.microsoft.com/WebPart/v2/ContentEditor" /> </WebPart> ]]> </AllUsersWebPart> </File>

Note that MainZone is name of the web part zone in the page added. The page added uses a custom layout which contains this web part zone. You can replace this with whatever web part zone id you have. Also notice that you can change the layout of the page in aspx file. The aspx file Publishing layout tag sets the layout used for this page.

<mso:PublishingPageLayout msdt:dt="string">

https://dev.erebportal.com/_catalogs/masterpage/eREBStudyPage.aspx, /_catalogs/masterpage/eREBStudyPage.aspx

</mso:PublishingPageLayout>

One last thing to note is depending if your web part is v2 or v3 the namespace attribute of webpart tag will differ. Will discuss about this in next post