Thursday, October 28, 2010

Create custom sites in Sharepoint using site definitions: step by step guide - part 2

In the previous part of this series I finished on creation of portal web manifest for branches of Contoso company. In this second part I will continue explanation of site creation customization for Sharepoint.

So  we created portal web manifest file with portal structure. For convenience I will duplicate it here:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <!-- _lcid="1033" _version="12.0.4518" _dal="1" -->
   3: <!-- _LocalBinding -->
   4: <portal xmlns="PortalTemplate.xsd">
   5:   <web name="Home" siteDefinition="ContosoBranchSite#0" displayName="$Resources:ContosoBranch,Site_Home_DisplayName;" description="">
   6:     <webs>
   7:       <web name="Sales" siteDefinition="ContosoBranchSite#1" displayName="$Resources:ContosoBranch,Site_Sales_DisplayName;" description="" />
   8:       <web name="IT" siteDefinition="ContosoBranchSite#2" displayName="$Resources:ContosoBranch,Site_IT_DisplayName;" description="" />
   9:       <web name="HR" siteDefinition="ContosoBranchSite#3" displayName="$Resources:ContosoBranch,Site_HR_DisplayName;" description="" />
  10:     </webs>
  11:   </web>
  12: </portal>

There are separate <web> element for each sub site in portal. Also we noticed that each <web> tag contains siteDefinition attribute which actually tells Sharepoint what site definition should be  used for this site:

  • ContosoBranchSite#0 – root portal site;
  • ContosoBranchSite#1 – Sales subsite;
  • ContosoBranchSite#2 – IT subsite;
  • ContosoBranchSite#3 – HR subsite.

ContosoBranchSite here is template name of site configuration, and number after # is configuration id. They are defined in separate webtemp file (don’t mess with webtempContosoBranchSitePortal.xml which is webtemp for portal itself. But now we are talking about webtemp file file for sub sites configuration). Similar to portal, webtemp file with sub sites declaration is located in 12/Template/{lcid}/xml folder. In our case this is 12/Template/{lcid}/webtempContosoBranchSite.xml (in order to avoid mess you should keep naming convention similar, so if we had webtempContosoBranchSitePortal.xml file for webtemp which contains ContosoBranchSitePortal template, for sub sites we will use webtempContosoBranchSite.xml name because it will contain ContosoBranchSite template). Content of webtempContosoBranchSite.xml is the following:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <Templates>
   3:   <Template Name="ContosoBranchSite" ID="10002">
   4:     <Configuration ID="0" Title="Home" Description="" Hidden="TRUE" ImageUrl="/_layouts/images/stsprev.png" DisplayCategory="Contoso" />
   5:     <Configuration ID="1" Title="Sales" Description="" Hidden="TRUE" ImageUrl="/_layouts/images/stsprev.png" DisplayCategory="Contoso" />
   6:     <Configuration ID="2" Title="IT" Description="" Hidden="TRUE" ImageUrl="/_layouts/images/stsprev.png" DisplayCategory="Contoso" />
   7:     <Configuration ID="3" Title="HR" Description="" Hidden="TRUE" ImageUrl="/_layouts/images/stsprev.png" DisplayCategory="Contoso" />
   8:   </Template>
   9: </Templates>

Here we defined template with ContosoBranchSite name. For this template we have 4 different configurations which were used in ContosoBranchSitePortalWebManifest.xml (of course you can use the same configurations for different sub sites in portal web manifest, but in our example all sites have different configurations as this is most common case). Note that in webtempContosoBranchSite.xml titles of configurations are the same as names of webs in portal web manifest. Also don’t mess with it: in portal web manifest “name” attribute of <web> tag means URL of sub site, while in webtemp file “Title” attribute of <Configuration> tag is just title of configuration. Note also that we specified Hidden=”TRUE” in order to hide these configurations from site template picker control on site creation page. We don’t need to create these sites separately – we need to create a whole portal with them in one operation.

Now lets return to webtemp file of portal and see what is the difference with webtemp file for sub sites. The main difference is that <Configuration> element for portal contains the following attributes:

  • ProvisionAssembly;
  • ProvisionClass;
  • ProvisionData.

These 3 attributes (and their values of course) make portal from a site. I described the meaning of these attributes in part 1. Another difference is that we have 4 different configurations for ContosoBranchSite template (sub sites template), and only 1 configuration for ContosoBranchSitePortal template (portal template).

So we created webtemp file for sub sites. Now it is time to define each sub site’s configuration. As I said in previous part, configurations are defined in onet.xml files stored in 12/Templates/SiteTemplates/{TemplateName}/xml folder. It is important to have folder name the same as “Name” attribute of <Template> element in webtemp file (although it is possible to override it using SetupPath attribute of <Template> element). In our case it will be 12/Templates/SiteTemplates/ContosoBranchSite/xml/onet.xml file.

How can we create onet.xml file for custom site template? It depends on your requirements. I prefer to copy OTB onet.xml file which corresponds to site template which is closest to particular business requirements. E.g. you can use OTB Team site or Publishing site template as base for further customization. As I said in first part we will use Publishing site in our examples as it is widely used in real life scenarios.

But there is one problem: there are many OTB onet.xml files in 12/Templates/SiteTemplates folder. How can we determine what file belongs to Publishing site template? Of course I could just say that it is located in this specific file, but it will not be so useful. I want to show you approach which you can use in order to make it by yourself in your development practice.  So one way to determine onet.xml for Publishing site is to search across all files content with “Publishing site” occurrence. But there is simpler way. If you already have site created using Publishing site template, then you can trace its properties into console using Sharepoint object model. We are interesting in the following properties of SPWeb class:

Property of SPWeb Mapped provision artifact
WebTemplate “Name” attribute of <Template> element in webtemp file
WebTemplateId “ID” attribute of <Template> element in webtemp file
Configuration “ID” attribute of <Configuration> element in webtemp and onet.xml

In order to trace these properties you can create simple console utility. I used my Resharper live template for Sharepoint utilities for that:

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         if (args.Length != 1)
   6:         {
   7:             Console.WriteLine("Usage: exe <site_collection_url>");
   8:             return;
   9:         }
  11:         using (var site = new SPSite(args[0]))
  12:         {
  13:             using (var web = site.OpenWeb())
  14:             {
  15:                 Console.WriteLine("WebTemplate: {0}", web.WebTemplate);
  16:                 Console.WriteLine("WebTemplateId: {0}", web.WebTemplateId);
  17:                 Console.WriteLine("Configuration: {0}", web.Configuration);
  18:             }
  19:         }
  20:     }
  21: }

So you just need to specify URL of the existing site in the command line and program will trace its properties. Here is its result for site created with Publishing site template:

   1: WebTemplate: CMSPUBLISHING
   2: WebTemplateId: 39
   3: Configuration: 0

There is only 1 file in 12/Template/{lcid}/xml folder which contains reference on CMSPUBLISHING: webtempsps.xml. After investigating it we will find that Publishing site onet.xml is located in 12/Templates/SiteTemplates/Publishing/xml folder:

   1: <Template Name="CMSPUBLISHING" ID="39" SetupPath="SiteTemplates\PUBLISHING">
   2:    <Configuration ID="0" Title="Publishing Site" Hidden="FALSE" ImageUrl="/_layouts/1033/images/PublishingCollaborationSite.gif" 
   3:        Description="A blank site for expanding your Web site and quickly publishing Web pages. Contributors can work on draft versions of pages and publish them to make them visible to readers. The site includes  document and image libraries for storing Web publishing assets."
   4:        FilterCategories="PublishingSiteTemplate"
   5:        SubWebOnly="TRUE"  DisplayCategory="Publishing"
   6:        VisibilityFeatureDependency="F6924D36-2FA8-4f0b-B16D-06B7250180FA">
   7:   </Configuration>
   8: </Template>

So all we need is just go to 12/Templates/SiteTemplates/Publishing/xml  and copy onet.xml to our folder 12/Templates/SiteTemplates/ContosoBranchSite/xml. Now our sub sites are ready for customization.

By default onet.xml of Publishing site template contains only one configuration

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <!-- _lcid="1033" _version="12.0.2220" _dal="1" -->
   3: <!-- _LocalBinding -->
   4: <Project Revision="3" Title="Publishing Site" ListDir="Lists" xmlns:ows="Microsoft SharePoint">
   5:  <NavBars>
   6:     ...
   7:  </NavBars>
   8:     <ListTemplates>
   9:     </ListTemplates>
  10:     <DocumentTemplates>
  11:         ...
  12:     </DocumentTemplates>
  13:     <BaseTypes>
  14:     </BaseTypes>
  15:     <Configurations>
  16:         <Configuration ID="-1" Name="NewWeb"/>
  17:         <Configuration ID="0" Name="Publishing"> 
  18:             ...
  19:         </Configuration>
  20:     </Configurations>    
  21:     <Modules>
  22:         ...
  23:     </Modules>
  24: </Project>

As you remember for our portal we have 4 different configurations, so the minimal change we need to do – is to copy default configuration with id=”0” 4 times in our onet.xml and paste it with different ids and names in order to correspond webtempContosoBranchSite.xml file:

   1: <Configurations>
   2:     <Configuration ID="0" Name="Home">
   3:         ...
   4:     </Configuration>
   5:     <Configuration ID="1" Name="Sales">
   6:         ...
   7:     </Configuration>
   8:     <Configuration ID="2" Name="IT">
   9:         ...
  10:     </Configuration>
  11:     <Configuration ID="3" Name="HR">
  12:         ...
  13:     </Configuration>
  14: </Configurations>

After that we can create our portal and all sub sites (including portal root site) will be created using the copy of OTB Publishing site template. At this moment sub sites have absolutely the same features as OTB publishing sites. But there is one big difference: we created them using custom site definitions so we are free now to add functionality to these sites as we wish without affecting OTB Publishing site template. But this is the theme of the next part of the series.

No comments:

Post a Comment