How to provision a Sandboxed Web Part through a custom module feature

As you probably know, you can use a module feature to provision a file to a SharePoint site. Through this feature you can provision images, Web Parts, master pages, pages, or whatever you like. In case you provision Web Part Pages, you can also provide some information and configuration elements, within the module element, in order to provision Web Parts inside the provisioned page.

For example, here you can see a code excerpt of a sample module element provisioning a custom Web Part.

< ?xml version="1.0" encoding="utf-8"?>
< Elements xmlns="http://schemas.microsoft.com/sharepoint/">
< Module Name="SampleWebPart" List="113" Url="_catalogs/wp">
< File Path="MyWebPart\MyWebPart.webpart" Url="MyWebPart.webpart" Type="GhostableInLibrary">
< Property Name="Group" Value="DevLeap Web Parts" />
< /File >
< /Module>
< /Elements>

And here you can see an example of a module element provisioning a custom page:

< ?xml version="1.0" encoding="utf-8"? >
< Elements xmlns="http://schemas.microsoft.com/sharepoint/">
< Module Name="CustomPages">
< File IgnoreIfAlreadyExists="True" Path="MyPage\MyPage.aspx" Url="MyPage.aspx" />
< /Module>
< /Elements>

The module element deploys a page with name MyPage.aspx, available in the MyPage folder of the current WSP solution, into the CustomPages library of the target site. In case the page is a Web Part Page, you can also provision Web Parts into the target page, directly using the element file. Here you can see an example of a custom Web Part Page:

<%@ Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
< asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
< SharePoint:ListItemProperty ID="ListItemProperty1" Property="BaseName" maxlength="40" runat="server"/>
< /asp:Content>
< asp:Content ID="Content12" ContentPlaceHolderId="PlaceHolderMain" runat="server">
< table cellpadding="4" cellspacing="0" border="0" width="100%">
< tr>
< td id="_invisibleIfEmpty" name="_invisibleIfEmpty" valign="top" width="100%">
< WebPartPages:WebPartZone runat="server" Title="loc:FullPage" ID="MainWebPartZone" FrameType="TitleBarOnly" />
< /td>
< /tr>
< /table>
< /asp:Content>

Notice the Content region targeting the PlaceHolderMain content place holder and the WebPartZone with ID MainWebPartZone. The module element can provision a Web Part into this page simply using the following syntax (see text in bold style):

< ?xml version="1.0" encoding="utf-8"? >
< Elements Id="efeaff94-0f17-4df2-8413-5abcbf1f813d" xmlns="http://schemas.microsoft.com/sharepoint/">
< Module Name="CustomWebPartPage">
< File Name="CustomWebPartPageInstance.aspx" Path="CustomWebPartPage.aspx" Url="CustomWebPartPage.aspx" IgnoreIfAlreadyExists="FALSE" NavBarHome="False" Type="Ghostable">
< AllUsersWebPart WebPartZoneID="MainWebPartZone" WebPartOrder="1">
< ![CDATA[ < webParts>
< webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
< metaData>
< type name="DevLeap.WebParts.SampleWebPart, DevLeap.WebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5" />
< importErrorMessage>Cannot import this Web Part.< /importErrorMessage>

< data>
< properties>
< property name="Title" type="string">Sample WebPart < /properties>
< /data>
< /webPart>
< /webParts>
]]>
< /AllUsersWebPart>
< /File>
< /Module>
< /Elements>

However, in case you want to provision a custom Sandboxed Web Part inside the provisioned Web Part Page, you cannot directly insert the Web Part you want to provision, because a Sandboxed Web Part needs to be wrapped into the native SPUserCodeWebPart Web Part of SharePoint. Here you can see a code sample that you can use to insert a Sandboxed Web Part into a Web Part Page that you provision through a module element:

<%@ Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
< asp:Content ID="Content1" ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
< SharePoint:ListItemProperty ID="ListItemProperty1" Property="BaseName" maxlength="40" runat="server"/>
< /asp:Content>
< asp:Content ID="Content12" ContentPlaceHolderId="PlaceHolderMain" runat="server">
< table cellpadding="4" cellspacing="0" border="0" width="100%">
< tr>
< td id="_invisibleIfEmpty" name="_invisibleIfEmpty" valign="top" width="100%">
< WebPartPages:WebPartZone runat="server" Title="loc:FullPage" ID="MainWebPartZone" FrameType="TitleBarOnly">
< WebPartPages:SPUserCodeWebPart runat="server" Description="My Sample Web Part" Title="SampleSandboxedWebPart" ID="g_d74cf5a2_70c1_4961_9a0f_26d5d2885af7" AssemblyFullName="DevLeap.WebParts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=88f7103039060a33" SolutionId="a1011e13-4f33-42bd-995f-a13df6969e80" TypeFullName="DevLeap.WebParts.SampleSandboxedWebPart" __MarkupType="vsattributemarkup" __WebPartId="{D74CF5A2-70C1-4961-9A0F-26D5D2885AF7}" WebPart="true" __designer:IsClosed="false">
< Properties>
< WebPartPages:SPUserCodeProperty Name="CustomProperty" Value="Value for custom Property">< /WebPartPages:SPUserCodeProperty>
< /Properties>
< /WebPartPages:SPUserCodeWebPart>
< /WebPartPages:WebPartZone>
< /td>
< /tr>
< /table>
< /asp:Content>

As you can see in bold style, there is an SPUserCodeWebPart Web Part instance directly declared within the WebPartZone inside the Web Part Page. The SPUserCodeWebPart references the real target Sandboxed Web Part using the AssemblyFullName, SolutionId, and TypeFullName attributes, and configures the Web Part instance using SPUserCodeProperty elements.