One of my current projects involves the new sandboxed deployment model. It is pretty fun and challenging to translate requirements into testable code. With the promise of deploying into environments like Office 365 there is a strong will to work around the limitations of the sandbox. Of course without resorting to solutions based on a senseless full trust proxy. One of the limitations is that there is no SPLimitedWebPartManager class. This means it is not possible to modify the Web Parts on a page using code. This is a bit of an issue since I want to deploy two related Web Parts that are connected together using a Web Part Connection. Overcoming the issue was fun enough for me to write about. So here goes. Web Parts, Web Part Connections and all fit for sandboxed deployment.
Find the sample project here.
Provisioning Web Parts
First step is to provision a Web Part to the page. Since the imperative approach using the SharePoint object model is not available in the sandbox we can only use declarative XML. My Web Parts are deployed to a page using a <Module> element which provisions a bunch of <File> elements, each of which contain various <AllUsersWebPart> elements.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="Module1">
<File Path="Module1\default.aspx" Url="demo.aspx">
<NavBarPage ID="1002" Name="Demo page" Position="End" />
<AllUsersWebPart ID="testProvider"
WebPartZoneID="Left"
WebPartOrder="1">
<![CDATA[...]]>
</AllUsersWebPart>
</File>
</Module>
</Elements>
This approach allows you to deploy a custom page which has preconfigured Web Parts. One note is that you cannot use this approach to deploy new Web Parts to existing pages since you will blast the existing page out of the water (try changing demo.aspx to default.aspx and see).
Provisioning the connection
During initial development the project ran fine with just loose Web Parts. After a while the need arose for connected Web Parts as a means to show master/detail data. So the quest for a declarative approach began and quickly turned up the new WebPartConnection element on a <File>. It also turned up that no-one has actually bothered to document it yet.
Using the <WebPartConnection> you now seem to have a declarative way to define connections between Web Parts. I definitely prefer XML over code especially since it also allows me to define connections for Web Parts that I deploy as part of a sandboxed solution
Note that I do NOT mean that Web Parts who's codebase is defined within an assembly deployed as part of a sandboxed solution. But, I mean that you can deploy a Web Part to a page whose codebase is part of a normal full-trust assembly, such as all built-in Web Parts types (XsltListView, Image, etc..).
There are generally only four attributes you are interested in. The ID of the provider and the ID of the connection point within that provider. The same goes for the consumer. Here's a sample that I use for my custom testing class that you can find in the attached demo project.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="Module1">
<File Path="Module1\default.aspx" Url="demo.aspx">
<AllUsersWebPart ID="testProvider">...</AllUsersWebPart>
<AllUsersWebPart ID="testConsumer">...</AllUsersWebPart>
<WebPartConnection ID="testConnection"
ProviderID="testProvider"
ProviderConnectionPointID="providerID"
ConsumerID="testConsumer"
ConsumerConnectionPointID="consumerID" />
</File>
</Module>
</Elements>
Getting sexy… Including a Web Part Transformer
In my later code I want to connect a row provider to a filter consumer. Connecting these Web Parts through the browser means that you get to fill in a dialog such as the following. You can put in the field mappings between the provider and the consumer. We need to do the same using the <WebPartConnection> and luckily it allows you to do it to!
The not so sexy part is the amount of current documentation on the mystic <WebPartTransformer> element. Other than it being a descendant of the <WebPartConnection> which allows you to point to an assembly / namespace there is nothing know to the human race outside of those in possession of the SharePoint kernel (Robin, send me a copy ok?). Not even the Microsoft.SharePoint DLL itself gives a hint of this hidden jewel. It took a bit of testing but I figured out how to it works.
The <WebPartTransformer> element points to an Assembly / Namespace because it is used like a <%@Register %> directive in ASP.NET. You point to a namespace and then use ASP.NET page markup to define the transformer. Since the ASP.NET markup uses < and > tags you need to throw it all in a CDATA section. It also appears that you must use the WebPartPages control prefix to make it work as expected. Here's a small sample taken from the POC.
<WebPartConnection ID="testConnection2"
ProviderID="testProvider2"
ProviderConnectionPointID="providerIDRow"
ConsumerID="testConsumer2"
ConsumerConnectionPointID="DFWP Filter Consumer ID">
<WebPartTransformer Assembly="Microsoft.SharePoint, ..."
Namespace="Microsoft.SharePoint.WebPartPages">
<![CDATA[<WebPartPages:SPRowToParametersTransformer
ConsumerFieldNames="URL"
ProviderFieldNames="Test" />]]>
</WebPartTransformer>
</WebPartConnection>
Voila. Web Parts with connections and even with transformers, all declarative and available inside the sandbox deployment model.
Hope it helps!