John Liu .NET

View Original

Silverlight + SharePoint - add to web part gallery

This article covers how to go about packaging a webpart for the Silverlight XAP file and deploy it to Web Part Gallery.

In the previous article I described the steps to create a SharePoint project and deploy the XAP file via a site feature.

Silverlight + SharePoint 2010 - package XAP file in a sandbox WSP Solution

But the user still needs to manually:

  1. Find the XAP file URL
  2. Manually insert a Microsoft out of box Silverlight Web Part
  3. Paste the XAP URL
  4. Save the Silverlight Web Part (may have to configure InitParams too).

Let's simplify this a little.

Go back to the <Elements> Module, and lets add a webpart

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Name="SilverlightCamera">
    <File Path="SilverlightCamera\SilverlightCamera.xap" Url="Style Library/SilverlightCamera.xap" />
    <File Path="SilverlightCamera\SilverlightCamera.webpart" Url="_catalogs/wp/SilverlightCamera.webpart" />
  </Module>
</Elements>

 

The webpart file itself is very simple: go to Web Parts Gallery, find and export Microsoft's Silverlight.webpart

<?xml version="1.0" encoding="utf-8"?>
<webParts>
  <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
    <metaData>
      <type name=
"Microsoft.SharePoint.WebPartPages.SilverlightWebPart, Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
      <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name="Title" type="string">Silverlight Camera Web Part</property>
        <property name="Description" type="string">A web part to display a Silverlight Camera.</property>
        <property name="Url" type="string">~sitecollection/Style Library/SilverlightCamera.xap</property>
        <property name="Height" type="int">300</property>
      </properties>
    </data>
  </webPart>
</webParts>

 

You may have noticed that the Url is a SiteCollection relative (~sitecollection/) path, so that no matter whether it's a root site collection or a managed path, we want the user's experience to be perfect.

Unfortunately - that syntax doesn't work, not without one extra hack via the Feature Event Receiver.

Feature Activated Event Receiver

 

Right click on the feature and add a new event receiver.  VS.NET will generate the CS file.

clip_image002

Figure: right click on the feature (.feature) and add an event receiver. 

 

Waldek has a magical event handler code that fixes this problem

http://blog.mastykarz.nl/inconvenient-content-query-web-part-server-relative-urls/

So I'll just post my bit of code here

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    // one day when I meet Waldek in person I will buy him beer
    // http://blog.mastykarz.nl/inconvenient-content-query-web-part-server-relative-urls/
    SPSite site = properties.Feature.Parent as SPSite;
    if (site != null)
    {
        SPList webPartsGallery = site.GetCatalog(SPListTemplateType.WebPartCatalog);
        SPListItemCollection allWebParts = webPartsGallery.Items;
        SPListItem webPart = (from SPListItem wp in allWebParts
                              where wp.File.Name == "SilverlightCamera.webpart"
                              select wp).SingleOrDefault();
        if (webPart != null)
        {
            string siteCollectionUrl = site.ServerRelativeUrl;
            if (!siteCollectionUrl.EndsWith("/"))
            {
                siteCollectionUrl += "/";
            }
            string fileContents = Encoding.UTF8.GetString(webPart.File.OpenBinary());
            fileContents = fileContents.Replace("~sitecollection/", siteCollectionUrl);
            webPart.File.SaveBinary(Encoding.UTF8.GetBytes(fileContents));
        }
    }
}

 

During Feature Activated - find the webpart and fix the ~sitecollection marker with the real site collection URL.

 

Deploy and activate the feature again.

clip_image002[5]

 

Success!  Our .webpart now appearing in the web part gallery.