Wednesday, April 2, 2014

Create SharePoint site using provisioning provider

In most cases, when we provision a site collection, we expect some customizations also to be created along with that site collection. Customizations can be branding, web parts, event receivers, etc..

There are several techniques to provision customized sites in SharePoint. Mostly important techniques are

  • Site definitions
  • Web templates
  • Provisioning Providers

Let’s assume we need to create a site collection programmatically with few web parts positioned in the home page. What do we normally do ? There are 2 approaches

The wrong way

We may use following steps to create the site

  1. Create a web service or console application to create site collection using built in template
  2. Add each web part to the page sequentially
  1. var spWebApp = SPWebApplication.Lookup(new Uri(appUrl));
  2. using (var site = spWebApp.Sites.Add
  3.     (siteUrl, siteTitle, "", 1033, "STS#0", login, userName, ""))
  4. {
  5.     //Add webpart 1
  6.     //Add webpart 2
  7. }

What is the problem with this approach?

The issue is that the Sites.Add method executes asynchronously. Hence we might be trying to add web parts or other customizations to a site which is still being provisioned.

The correct way

The best practice is to provision such site collection using a provisioning provider. Following are the steps in creating a site using provisioning provider.

     1. Create custom behavior using new class extending SPWebProvisioningProvider

  1. public override void Provision(SPWebProvisioningProperties props)
  2. {
  3.   var web = (SPWeb)props.Web;
  4.   web.ApplyWebTemplate("ContosoSites#1");
  5.   //Change the description to demonstrate
  6.   web.Description = "created by provisioning provider";
  7.  
  8.   //Add webpart 1
  9.   //Add webpart 2
  10.   web.Update();
  11. }
 

    2. Create site definition

Site definition contain 2 files, namely “Onet.xml” and “webTemp.xml”. Following is a sample “Onet.xml” file

image

   3. Specify ProvisionAssembly and ProvisionClass elements in web template file

  1. <Templates xmlns:ows="Microsoft SharePoint">
  2.   <Template Name="ContosoSites" ID="10002">    
  3.     <Configuration ID="0"
  4.                    Title="Contoso HR Site"
  5.                    Hidden="FALSE"
  6.                    ImageUrl="/_layouts/images/CPVW.gif"
  7.                    ProvisionAssembly="STSTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ec660d77d5010c78"
  8.                    ProvisionClass="STSTest.ContosoProvisioningProvider"
  9.                    Description="Contoso HR Site"
  10.                    DisplayCategory="Contoso Sites">
  11.     </Configuration>
  12.     <Configuration ID="1"
  13.                    Title="Contoso HR Site"
  14.                    Hidden="True"
  15.                    ImageUrl="/_layouts/images/CPVW.gif"
  16.                    Description="Contoso HR Site"
  17.                    DisplayCategory="Contoso Sites">
  18.     </Configuration>
  19.   </Template>
  20. </Templates>

You may notice that, we’ve created two configuration elements for same “Contoso HR Site”. This is to avoid circular reference when applying the template from the provisioning provider.

In addition to the configuration which attaches the provisioning provider we will create a hidden configuration as well. From the provisioning provider we will apply the hidden configuration. By doing that we can avoid the circular reference

   4. Deploy the solution

   5. Create new site

         image

No comments: