Sunday 18 September 2011

How to create a complex Custom Site Definition with Visual Studio 2010 using SPWebProvisioningProvider

In my previous article (How to Create a simple Custom Site Definition with Visual Studio 2010) I built a really simple custom site definition with some code behind. I used a Microsoft article for that, so the project was almost the same. In this part I am going to use the same example, so if you want to follow exactly the same, I recommend you to download the example and work with it.

Having a Custom Site Definition that looks like this (see below) we are going to add a Provisioning Provider plus extra stuff.
image

The first thing we are going to do is to explain exactly what a SPWebProvisioningProvider class is and can do for us.
SPWebProvisioningProvider: Provides a handler for responding to Web site creation.
Microsoft give us a big advise in the MSDN documentation:

Be careful about calling the ApplyWebTemplate method within a Web site provisioning callback. Calling this method inside a provisioning callback that is defined within the same site definition configuration that is being applied can cause an infinite loop. Instead, create two similar site definition configurations within the site definition, one that is visible and one that is hidden. The configuration can then contain a provisioning assembly callback that applies the hidden configuration to Web sites.

I don’t think this definition was enough to understand what you can do with this class, but I am going to give my simple explanation. This class allows you to use existing templates for your new site.
For example if you have fallen in love with the Wiki Template and you don’t want to waste your time building a custom site definition, adding all the stuff that the Wiki template has, just because you want to go home or just want to play a football game with some friends, What do you do?, you call SPWebProvisioningProvider override it and add your code.
How do we do that? simple! by creating a simple class we will add in the Custom Site Definition.


Follow this step by step tutorial based in my previous article (you don’t need it but if you are new in this field it will make the things simpler for you, your dog and your family.


Step 1
Let’s go to create that famous class, so go to the project (netsourcecodeSiteDefinition) right click->Add->Class and call it ProvisioningNSC:
image


Step 2
Copy and paste the code below, as you can see we get the SPWebProvisioningProvider class as base and override one of the methods. As you can see the only thing we are doing is setting the Wiki template. (SPWebSPWebProvisioning.GetData)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
namespace netsourcecodeSiteDefinition
{
    class ProvisioningNSC : SPWebProvisioningProvider
    {
        public override void Provision(SPWebProvisioningProperties props)
        {
            //## Getting the website object
            SPWeb _wWeb = props.Web;       
           
            //## Applying a nice Wiki template       
            _wWeb.ApplyWebTemplate(SPWebTemplate.WebTemplateWIKI);
        }
    }
}

Step 3
The next step will  be to register our class in the site definition file webtemp_netsourcecodeSiteDefinition.xml, if you have a look we have different options there, you can change the icon in the ImageURL, description, title etc. Be sure ProvisionAssembly has the local assembly name. ProvisionClass contains Namespace+YourProvisionFileName.

<?xml version="1.0" encoding="utf-8"?>
<Templates xmlns:ows="Microsoft SharePoint">
  <Template Name="netsourcecodeSiteDefinition" ID="10000">   
    <Configuration 
      ID="0"
      Title="netsourcecodeSiteDefinition"
      Hidden="FALSE"
      ImageUrl="/_layouts/images/CPVW.gif"
      Description="netsourcecodeSiteDefinition"
      DisplayCategory="SharePoint Customizations"
      ProvisionAssembly="$SharePoint.Project.AssemblyFullName$"
      ProvisionClass="netsourcecodeSiteDefinition.ProvisioningNSC">
    </Configuration>
  </Template>
</Templates>

Step 4
Let’s go to modify our onet.xml. We are going to add three more lists

<?xml version="1.0" encoding="utf-8"?>
<Project Title="netsourcecodeSiteDefinition" Revision="2" ListDir="" xmlns:ows="Microsoft SharePoint" xmlns="http://schemas.microsoft.com/sharepoint/">
  <NavBars>
    <NavBar Name="$Resources:core,category_Lists;" Prefix="&lt;table border='0' cellpadding='4' cellspacing='0'&gt;" Body="&lt;tr&gt;&lt;td&gt;&lt;table border='0' cellpadding='0' cellspacing='0'&gt;&lt;tr&gt;&lt;td&gt;&lt;img src='/_layouts/images/blank.gif' id='100' alt='' border='0'&gt;&amp;nbsp;&lt;/td&gt;&lt;td valign='top'&gt;&lt;a id='onetleftnavbar#LABEL_ID#' href='#URL#'&gt;#LABEL#&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;" Suffix="&lt;/table&gt;" ID="1003" />
  </NavBars>
  <Configurations>
    <Configuration ID="0" Name="netsourcecodeSiteDefinition">
      <Lists>
        <List
          FeatureId="00BFEA71-A83E-497E-9BA0-7A5C597D0107"
          Type="107"
          Title="Project Tasks"
          Url="$Resources:core,lists_Folder;/$Resources:core,tasks_Folder;"
          QuickLaunchUrl="$Resources:core,lists_Folder;/$Resources:core,tasks_Folder;/AllItems.aspx" />
        <List
          FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101"
          Type="101"
          Title="$Resources:core,shareddocuments_Title;"
          Url="$Resources:core,shareddocuments_Folder;"
          QuickLaunchUrl="$Resources:core,shareddocuments_Folder;/Forms/AllItems.aspx" />
        <List
          FeatureId="00BFEA71-D1CE-42de-9C63-A44004CE0104"
          Type="104"
          Title="$Resources:core,announceList;"
          Url="$Resources:core,lists_Folder;/$Resources:core,announce_Folder;">
              <Data>
                <Rows>
                  <Row>
                    <Field Name="Title">$Resources:onetid11;</Field>
                    <Field Name="Body">$Resources:onetid12;</Field>
                    <Field Name="Expires"><ows:TodayISO/></Field>
                  </Row>
                </Rows>
              </Data>
        </List>
        <List
          FeatureId="00BFEA71-EC85-4903-972D-EBE475780106"
          Type="106"
          Title="$Resources:core,calendarList;"
          Url="$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;"
          QuickLaunchUrl="$Resources:core,lists_Folder;/$Resources:core,calendar_Folder;/Calendar.aspx"
          EmailAlias="$Resources:core,calendar_EmailAlias;" />
      </Lists>
      <SiteFeatures>
      </SiteFeatures>
      <WebFeatures>
      </WebFeatures>
      <Modules>
        <Module Name="DefaultBlank" />
      </Modules>
    </Configuration>
  </Configurations>
  <Modules>
    <Module Name="DefaultBlank" Url="" Path="">
      <File Url="default.aspx">
      </File>
    </Module>
  </Modules>
</Project>

Step 5
The whole solution should look like this now:
image
As soon as you create the site, this is what you will get!


image


Conclusion: As you can see when you provision a site you can specify anything, you can even add custom lists you already created.



Download the code!
image

No comments: