Force Left Nav To at least 200 Pixels wide
Force Body To at least 500 Pixels high
SharePoint MindsharpBlogs > Nancy Brown > Posts

 Single Post

Nov 08
Published: November 08, 2011 04:11 AM by  Nancy Brown
The new (2010) way to create custom site definitions is the Web Template, which is Sandbox-safe. These can be created using the Save-site-as-template on the Site Settings page, but that creates a humongous beast containing all the Fields, Content Types, Lists… way more stuff than is truly needed, so a better solution is the Do-It-Yourself (DIY) WebTemplate.
 
A DIY Sandboxed WebTemplate solution might look like this in Solution Explorer, with a Site Feature to deploy the WebTemplate to the Solutions Gallery, and another hidden Feature, (WebFeature in this case), to handle the custom provisioning of a new site.
 
Solution Explorer for Custom Web Template
 
This post is about just one aspect of this scenario: how to provision web parts to a page using a provisioning Feature in a Sandboxed WebTemplate Solution. The page in this example is default.aspx, a clone of the STS#1 (Blank Site) default.aspx, with some added text and an image. SiteFeature deploys the actual Web Template - that's everything in the FRED folder: ONet.xml and Elements.xml (which contains only a WebTemplate element). WebFeature deploys everything in the ProvisionModule folder: default.aspx and Elements.xml, which contains such bits as ListInstance elements, Modules, and PropertyBag elements. WebFeature is called by ONet.xml to help provision a new site.
 
List View Web Parts
 
Typically, the ONet.xml file for a Do-It-Yourself WebTemplate is created by selectively copying/pasting from the base site definition's ONet.xml. This could lead one to thinking "Oh, I’ll just grab the <List> elements too." Unfortunately, that won't work. Well, specifying the <List> element in ONet.xml will create the list, but if a <View> element is used in the provisioning Feature's xml to create the matching web part, that fails with this sort of error message in the log:
 

Failed to find a suitable list id for doc 'default.aspx' given List template attribute 'Lists/Announcements'.

Failed with 0x80004005 to create the view query or web parts for web /fred, site collection (unspecified), URL default.aspx

Solution - instead of using <List> in ONet.xml, use the new ListInstance element in the provisioning Feature (WebFeature in this example). Looks like this:
 

<?xml version="1.0" encoding="utf-8"?>

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

  <ListInstance FeatureId="{00bfea71-d1ce-42de-9c63-a44004ce0104}" TemplateType="104"

          Title="Announcements"

          Description=""

          Url="Lists/Announcements"

          OnQuickLaunch="TRUE"

          RootWebOnly="FALSE" >

    <Data>

      <Rows>

        <Row>

          <Field Name="Title">Keep the Team Up-To-Date!</Field>

          <Field Name="Body">

            Use this List to post any SharePoint 2010 tips or tricks

          </Field>

          <Field Name="Expires">12/31/2011</Field>

        </Row>

      </Rows>

    </Data>

  </ListInstance>

  <Module Name="ProvisionModule" Url="">

    <File Path="ProvisionModule\default.aspx" Url="default.aspx" Type="Ghostable">

      <View List="Lists/Announcements"

            BaseViewID="1"

            WebPartOrder="0" WebPartZoneID="Left" >     

      </View>

    </File>

  </Module>

</Elements>

 
Other web parts, with customizations
 
There are at least a couple of options here. Both involve customizing a web part through the browser, and then harvesting that customization somehow. Option one is exporting the customized web part and using that data in an AllUsersWebPart element. Option two is using the Save-site-as-template to create a WSP that is then imported into Visual Studio, followed by extracting the BinarySerializedWebPart element from it.
 
  AllUsersWebPart
 
First customize a web part through the browser. The image web part is pretty straightforward, and we can use images in the {SharePointRoot} images folder, so let's use that. For option one, the AllUsersWebPart, we'll set the web part to show templogo.gif, left-justified, with no chrome and no title, then use the Export option.
 
Export an Image Web Part
 
Open the exported .dwp or .webpart file in Notepad, and copy the entire WebPart element. The opening WebPart tag only needs the xmlns="http://schemas.microsoft.com…" attribute, so delete any others. Usually it is best also to delete the child elements that are default values as well. In the provisioning Feature's Elements.xml, add an AllUsersWebPart element with a CDATA section to contain the WebPart element just created from the export. (The AllUsersWebPart element can "host" almost every web part.) Note that the WebPartZoneID and WebPartOrder should be attributes of the AllUsersWebPart element, not child elements of the WebPart element. The AllUsersWebPart is added as a child element to the File element, just like the View element in the example above. The AllUsersWebPart should look something like this:
 

      <AllUsersWebPart WebPartZoneID="Left" WebPartOrder="1">

        <![CDATA[

          <WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">

            <Title />

            <FrameType>None</FrameType>

            <FrameState>Normal</FrameState>

            <MissingAssembly>Cannot import this Web Part.</MissingAssembly>

            <Assembly>Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>

            <TypeName>Microsoft.SharePoint.WebPartPages.ImageWebPart</TypeName>

            <ImageLink xmlns="http://schemas.microsoft.com/WebPart/v2/Image">/_layouts/images/templogo.gif</ImageLink>

            <VerticalAlignment xmlns="http://schemas.microsoft.com/WebPart/v2/Image">Middle</VerticalAlignment>

            <HorizontalAlignment xmlns="http://schemas.microsoft.com/WebPart/v2/Image">Left</HorizontalAlignment>

          </WebPart>

        ]]>

      </AllUsersWebPart>

 
  BinarySerializedWebPart
 
Going back to the site where the image Web Part was customized earlier, let's add another web part, an XML Viewer, and use it to display the first five titles in a blog - that means adding some XSL. The XML Viewer Web Part is a bit different from most other web parts - one of its properties is an XSL transform. That means if one exports it, there is already a CDATA section in the XML. Here's an example with the embedded CDATA section highlighted:
 

<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">

  <Title>XML Viewer</Title>

  <FrameType>Default</FrameType>

  <Description>Transforms XML data using XSL and shows the results.</Description>

  <ZoneID>Left</ZoneID>

  <PartOrder>0</PartOrder>

  <FrameState>Normal</FrameState>

  <MissingAssembly>Cannot import this Web Part.</MissingAssembly>

  <Assembly>Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>

  <TypeName>Microsoft.SharePoint.WebPartPages.XmlWebPart</TypeName>

  <XMLLink xmlns="http://schemas.microsoft.com/WebPart/v2/Xml">http://www.tinyurl.com/SPTeamBlog</XMLLink>

  <XML xmlns="http://schemas.microsoft.com/WebPart/v2/Xml" />

  <XSLLink xmlns="http://schemas.microsoft.com/WebPart/v2/Xml" />

  <XSL xmlns="http://schemas.microsoft.com/WebPart/v2/Xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="html" indent="yes"/>

<xsl:param name="TITLE"/>

<xsl:template match="rss">

  <div style="background:#ffffff; padding:0; font-size:10px;">

      <xsl:for-each select="channel/item[position() &lt; 6]">

        <a href="{link}" target="_new"><xsl:value-of select="title"/></a><br/>

      </xsl:for-each>

  </div>

</xsl:template>

</xsl:stylesheet>]]></XSL>

  <PartStorage xmlns="http://schemas.microsoft.com/WebPart/v2/Xml" />

</WebPart>

 
CDATA sections cannot be nested, so the AllUsersWebPart element is not much help here; but a BinarySerializedWebPart can be. Create a WSP for that site using the Save-site-as-template option on the Site Settings page. In the Solutions Gallery, click the name of the solution to download a copy to the hard drive. Fire up Visual Studio, and create a new Import SharePoint Solution Package project. Import the solution just downloaded, taking all the defaults. In Solution Explorer, expand the Modules folder, and find a folder that starts with "_SiteTemplates" - that's where the BinarySerializedWebPart will be. (In this example, the Site used for the web parts is a Blank Site - STS#1). Double-click Elements.xml to view it in the Visual Studio editor.
 
BinarySerializedWebPart XML
 
Copy the entire BinarySerializedWebPart element, and paste it inside the File element as before. Be sure to edit the Url attribute to match the deployment scenario, which in this case, would be just "default.aspx", and don't forget to update the WebPartOrder and WebPartZoneId attributes. The Module element with these three web parts now looks like this:
 

  <Module Name="ProvisionModule" Url="">

    <File Path="ProvisionModule\default.aspx" Url="default.aspx" Type="Ghostable">

      <View List="Lists/Announcements"

            BaseViewID="1"

            WebPartOrder="0" WebPartZoneID="Left"

      >

      </View>

      <AllUsersWebPart WebPartZoneID="Left" WebPartOrder="1">

        <![CDATA[

          <WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">

            <Title />

            <FrameType>None</FrameType>

            <FrameState>Normal</FrameState>

            <MissingAssembly>Cannot import this Web Part.</MissingAssembly>

            <Assembly>Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>

            <TypeName>Microsoft.SharePoint.WebPartPages.ImageWebPart</TypeName>

            <ImageLink xmlns="http://schemas.microsoft.com/WebPart/v2/Image">/_layouts/images/templogo.gif</ImageLink>

            <AlternativeText xmlns="http://schemas.microsoft.com/WebPart/v2/Image">Temp Logo</AlternativeText>

            <VerticalAlignment xmlns="http://schemas.microsoft.com/WebPart/v2/Image">Middle</VerticalAlignment>

            <HorizontalAlignment xmlns="http://schemas.microsoft.com/WebPart/v2/Image">Left</HorizontalAlignment>

          </WebPart>

        ]]>

      </AllUsersWebPart>

      <BinarySerializedWebPart>

        <GUIDMap />

        <WebPart ID="{d5d0e278-b7b8-4ca0-987a-08643cf85f50}"

                 WebPartIdProperty="" List="" Type="0" Flags=""

                 DisplayName="" Version="2"

                 Url="default.aspx"

                 WebPartOrder="2" WebPartZoneID="Left"

                 IsIncluded="True" FrameState="0"

                 WPTypeId="{1077a241-f086-1411-9623-a67ec78bc114}"

                 SolutionId="{00000000-0000-0000-0000-000000000000}"

                 Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

                 Class="Microsoft.SharePoint.WebPartPages.XmlWebPart"

                 Src=""

                 AllUsers="AQUAAAACKgBJACkAAz4AAAIqAEoAKQADPQAAAQIAKQAD//80VHJhbnNmb3JtcyBYTUwgZGF0YSB1c2luZyBYU0wgYW5kIHNob3dzIHRoZSByZXN1bHRzLg8BIAApAAP//xsvX2xheW91dHMvaW1hZ2VzL21zeG1sbC5naWYPAVEAXQAD///EAWh0dHA6Ly9zaGFyZXBvaW50Lm1pY3Jvc29mdC5jb20vYmxvZy9fbGF5b3V0cy9mZWVkLmFzcHg/eHNsPTImd2ViPSUyRmJsb2cmcGFnZT0yMjY1NDg5Ny01MzU1LTQwOWItODZiNy0xOTI5NTViYjU3ZDgmd3A9NjhjODA0NWYtMzcyZC00Zjg3LTkzNTMtNzk5MzZhY2ZhZDQ4JnBhZ2V1cmw9JTJGYmxvZyUyRlBhZ2VzJTJGZGVmYXVsdCUyRWFzcHgPARQAXQAE///sAzw/eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04Ij8+DQo8eHNsOnN0eWxlc2hlZXQgdmVyc2lvbj0iMS4wIiB4bWxuczp4c2w9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvWFNML1RyYW5zZm9ybSI+DQo8eHNsOm91dHB1dCBtZXRob2Q9Imh0bWwiIGluZGVudD0ieWVzIi8+DQo8eHNsOnBhcmFtIG5hbWU9IlRJVExFIi8+DQo8eHNsOnRlbXBsYXRlIG1hdGNoPSJyc3MiPg0KICA8ZGl2IHN0eWxlPSJiYWNrZ3JvdW5kOiNmZmZmZmY7IHBhZGRpbmc6MDsgZm9udC1zaXplOjEwcHg7Ij4NCiAgICAgIDx4c2w6Zm9yLWVhY2ggc2VsZWN0PSJjaGFubmVsL2l0ZW1bcG9zaXRpb24oKSAmbHQ7IDZdIj4NCiAgICAgICAgPGEgaHJlZj0ie2xpbmt9IiB0YXJnZXQ9Il9uZXciPjx4c2w6dmFsdWUtb2Ygc2VsZWN0PSJ0aXRsZSIvPjwvYT48YnIvPg0KICAgICAgPC94c2w6Zm9yLWVhY2g+DQogIDwvZGl2Pg0KPC94c2w6dGVtcGxhdGU+DQo8L3hzbDpzdHlsZXNoZWV0Pg8P"

                 PerUser="AQUAAAACKgBJACkAAz4AAAIqAEoAKQADPQAAAQQAKQAD//8UU2hhcmVQb2ludCBUZWFtIEJsb2cPDw==" />

      </BinarySerializedWebPart>

    </File>     

  </Module>

 
Here's a new site is created from that DIY WebTemplate, displaying the customized web parts on default.aspx.
 
Site created from Custom Web Template, with Web Parts
 
Hope that helps!


 Comments

No comment(s) to show

 Add Comment

* Required Field
Your Name *
Your Blog Url
Message Subject *
Message Body *