This one turned out to be an fascinating result – at first I thought that I can just copy a fixed “Module” feature from a farm solution and that it will work smoothly within a sandbox solution. For instance:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="MyPages" Path="MyPages" Url="Pages">
<File Url="mypage.aspx" Path="mypage.aspx" Type="GhostableInLibrary">
<Property Name="Title" Value="Home" />
<Property Name="ContentType" Value="Welcome Page" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/MyWelcome.aspx, My Welcome Page" />
<AllUsersWebPart WebPartZoneID="BottomLeftZone" WebPartOrder="1">
<![CDATA[
<WebPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/WebPart/v2">
<Title>Search Box</Title>
<FrameType>None</FrameType>
<Description>Displays a search box that allows users to search for information.</Description>
<MissingAssembly>Cannot import this Web Part.</MissingAssembly>
<Assembly>Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
<TypeName>Microsoft.SharePoint.Portal.WebControls.SearchBoxEx</TypeName>
</WebPart>]]>
</AllUsersWebPart>
</File>
</Module>
</Elements>
As you see, this is a honestly simple “Module” elements file with a single “File” element that provisions a publishing page containing one web part to the standard “Pages” library. The “mypage.aspx” file is the standard template redirection one-liner page that you can take from any of the standard SharePoint publishing site definitions:
<%@ Page="" Inherits="Microsoft.SharePoint.Publishing.TemplateRedirectionPage,Microsoft.SharePoint.Publishing,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %><%@ Reference="" VirtualPath="~TemplatePageUrl" %><%@ Reference="" VirtualPath="~masterurl/custom.master" %>
So, when I added this feature to a sample sandbox solution of mine, deployed the latter and activated the feature I immediately noticed two reasonably unpleasant issues:
- the first one was that the file was provisioned in a draft state (not check in)
- the second was even worse – the web part was missing on the page
I started wondering what may be causing these issues and thought that at least the first one was not that serious – after all with a small bit of code in a feature receiver it should be possible to publish the provisioned page or pages. But then thinking about the second issue I realized that it will require much more than several lines of code if I want to get that fixed with custom programming (and why should I get into that much distress since this is supposed to be available out-of-the-box). The fact was that I already had the code that does the whole trick of parsing the “Module” elements file, parses a selected “File” element and adds the web parts to a web part page by the SharePoint object model – I had used that in my “web part administrator” tool, even if I wasn’t sure if the code (and it was several hundred lines of code) would work normally in a sandbox.
Reluctant to use this cumbersome “fix”, it occurred to me that I can try by the built-in SharePoint feature of saving a site as a template which in SharePoint 2010 makes a “wsp” package (which is a sandbox solution) that contains a “Module” feature provisioning all files (including publishing pages) in the site. My plot was simple – after I make the “wsp” package of my test site with publishing pages I will make a sub-site based on it and will check whether the provisioning of the publishing pages will fail in the same miserable way and if it doesn’t I will open the “wsp” file and inspect the XML of the “Module” element to see what does the trick.
So, as I suspected, the first part went smoothly which meant that the “save as template” feature worked perfectly with publishing pages although the “save site as template” command is missing in the “site settings” page of sites based on publishing site templates and you have to navigate to it manually – _layouts/savetmpl.aspx (it’s really fascinating to know why it is hidden in the first place, I can only suspect that there is a serious reason for that).
Then came the fascinating part of checking the “Module” and “File” elements in the “Module” feature containing the publishing pages (really I was hard with just one page) – first I reproduced the normal working of the feature by copying the elements without any changes and then started to remove parts, that I thought, weren’t necessary so that I may possibly find out which is the critical part. First I check the attributes of the “Module” and “File” elements but there was nothing superfluous or peculiar there (the “Level” attribute of the “File” element was not present), it wasn’t a “Property” element for the “_ModerationStatus” system column any. Then I saw a huge chunk worth deleting – the “Property” element of the “MetaInfo” system column – it basically contains the concatenated values of all other fields and file property bag items of the provisioned file – and after I deleted it the feature started to behave in the exactly same way as my first feature. I had a closer look at the “MetaInfo” element and after some hard found out that it is this part that does the trick:
vti_setuppath:SR|SiteTemplates\SPS\Defaulting.aspx
The meaning of this one was nearly clear to me – instead of by the “aspx” file provided in the feature the publishing page should use a file already available in the subfolders of the “14” hive. Another thing that immediately occurred to me was that the “Module” element also accepts a “SetupPath” attribute, so I quickly rewrote my first feature so that it now looked like:
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="MyPages" SetupPath="SiteTemplates\SPS" Url="Pages">
<File Url="mypage.aspx" Path="defaulting.aspx" Type="GhostableInLibrary">
<Property Name="Title" Value="Home" />
<Property Name="ContentType" Value="Welcome Page" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/MyWelcome.aspx, My Welcome Page" />
<AllUsersWebPart WebPartZoneID="BottomLeftZone" WebPartOrder="1">
<![CDATA[
<WebPart xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.microsoft.com/WebPart/v2">
<Title>Search Box</Title>
<FrameType>None</FrameType>
<Description>Displays a search box that allows users to search for information.</Description>
<MissingAssembly>Cannot import this Web Part.</MissingAssembly>
<Assembly>Microsoft.Office.Server.Search, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
<TypeName>Microsoft.SharePoint.Portal.WebControls.SearchBoxEx</TypeName>
</WebPart>]]>
</AllUsersWebPart>
</File>
</Module>
</Elements>
So, as you see there are only two small changes in the attributes of the “Module” and “File” attributes:
- the first one is the adding of the “SetupPath” attribute to the “Module” element and removing the existing “Path” attribute
- the second one is the changing of the value of the “Path” attribute of the “File” element to “defaulting.aspx”
The thought of these two attributes is that under this path “14\Template\SiteTemplates\SPS\defaulting.aspx” there is a standard SharePoint file which is exactly a template redirection page, exactly the same as the one that I showed above. This means that instead of the “aspx” file in the feature (which can be removed from the feature really) an existing standard SharePoint file will be used for the provisioning of the publishing page. The other clear thing is that the cumbersome “MetaInfo” property is also not necessary since the “SetupPath” attribute of the “Module” element achieves the same result much more pleasingly.
And several words as a small conclusion – even if the syntax of the standard SharePoint feature elements seem the same there’re certain differences in the way the SharePoint artifacts get provisioned in farm and sandbox solutions. So, I guess, we can expect similar smaller or larger surprises with the new SharePoint 2010 and especially with the new sandbox solutions.
Check it out:Stefan Stanev’s SharePoint blog











Answers Rating