Hello kind readers…
Sandbox solutions… funny, challenging.. Pathetic… painful.. Wonderful.. Everything a developer wants to feel energized :)
So recently we were building one of such sandbox solution which required a lot of default web parts on different pages in a larger hierarchy of sites and writing code to do(sandbox does not have limited webpart manager) that or doing it manually was a pain. So we wanted to automate the process and then while venturing around I found some insights on how to add default web parts like CQWP on a default.aspx.. But still we wanted more flexibility...
so the thing is when you are adding a page using a page layout and template redirection with some default content on it through the sandbox solution module element then the page should come from a path that is physically located on the disk (mainly 14 hive folder ..site templates), so taking an example of the default.aspx we need the xml as
<Module Name="SitePages" Url="Pages" SetupPath="SiteTemplates\SPS"> //The SetupPath should be pointing to the physical location of the file so the site templates folder
<File Path="default.aspx" Url="default.aspx" Type="GhostableInLibrary"> //the setup path has the folder name and the file PATH has the file name from this folder which in this case is default.aspx so directly default.aspx
<Property Name="Title" Value="Home Page" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/yourLayout.aspx, Homepage" />
<Property Name="ContentType" Value="your content type" />
//then you add the webpart xml in with the respective webpart zone id as in you layout
<AllUsersWebPart WebPartOrder="1" WebPartZoneID="LeftColumn">
<![CDATA[
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Name of your webpart class, four part assembly name" />
<importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Working</property>
<property name="Description" type="string">My WebPart</property>
<property name="ChromeType" type="chrometype">TitleOnly</property>
</properties>
</data>
</webPart>
</webParts>]]>
</AllUsersWebPart>
</File>
</Module>
Now if you add a default sharepoint webpart like the CQWP here by exporting the xml and adding it here.. It will work without a problem and you have a default web part on the default.aspx… but what about the CUSTOM webparts … coz if you add a custom web part to a page manually through UI and export the xml from it… you will get the same xml for all webparts with meta data properties as,
<type name="Microsoft.SharePoint.WebPartPages.SPUserCodeWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
Now this SPUserCodeWebpart is always there so if you just copy paste this xml it won't load you webpart on deployment as it does not know which webpart you want… and if you copy the xml from the .webpart xml from your solution it will have the <$SharePoint.Project.AssemblyFullName$> as the assembly name which is resolved by VS to the respective assembly name automatically. So how do you add a custom webpart then, well that can be done with some modifications above as,
<Module Name="SitePages" Url="Pages" SetupPath="SiteTemplates\SPS"> //The SetupPath should be pointing to the physical location of the file so the site templates folder
<File Path="default.aspx" Url="default.aspx" Type="GhostableInLibrary"> //the setup path has the folder name and the file PATH has the file name from this folder which in this case is default.aspx so directly default.aspx
<Property Name="Title" Value="Home Page" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/yourLayout.aspx, Homepage" />
<Property Name="ContentType" Value="your content type" />
//then you add the webpart xml in with the respective webpart zone id as in you layout
<AllUsersWebPart WebPartOrder="1" WebPartZoneID="LeftColumn">
<![CDATA[
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Name of your webpart class, four part assembly name" /> //the four part assembly name to be added for your assembly, could be found in manifest xml in your package file in VS.
<importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
//You need to add the solution ID of the solution this webpart is a part of, again can found at manifest xml
//this makes sense coz with sandbox solution SharePoint should know where to look for the assembly
<Solution SolutionId="your solution GUID" xmlns="http://schemas.microsoft.com/sharepoint/" />
</metaData>
<data>
Now with the Solution element in your meta data properties … the Four part assembly name of the assmebly your webpart is a part of .. The name class of webpart..
The setup path pointing to a physical location and File path picking up default.aspx from that setup path folder
Your deployed default.aspx page will have the custom webparts as well on the page and not just SharePoint webparts, basically the important things here are,
- In <Module> element the setup path of the module should point to a physical folder on the disk, mainly SiteTemplates\SPS
- In <File> element the Path attribute should have the name of the file residing in the folder name you gave in set up path
- The webpart xml <type> element should have the complete type name of the webpart class plus the full 4 part assembly name
- The webpart xml should have the <solution> element in the <metatdata> section giving the solution guid ID which the webpart is part of
With these things in place you can have your custom webpart on the page. Now this is not only true for default.aspx … you can use this approach for any page… what you would need to change is just the URL attribute of the <File> element and layouts property to you’re the respective layout.... So if you want to have a page with URL and name as MyWork.aspx then the xml changes would be only,
<Module Name="SitePages" Url="Pages" SetupPath="SiteTemplates\SPS"> //The SetupPath should be pointing to the physical location of the file so the site templates folder
<File Path="default.aspx" Url="MyWork.aspx" Type="GhostableInLibrary"> //the setup path has the folder name and the file PATH has the file name from this folder which in this case is default.aspx so directly default.aspx and URL has the new name you want to give
<Property Name="Title" Value="My Page" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/Somelayout.aspx, whatever" />
Rest remains same.
Hope this helps you in some way to speed up or automate your deployment if you mix it up with web templates :)
- "T"