Wednesday 25 September 2013

Customization of SharePoint Site Definition & what is the best way to do that?

Introduction
You can do customization on each of the sites created from the site definition OR you can customize the out of the box site definition itself. However, a SharePoint service pack upgrade would break any customization to out of box site definition. Then what is the best way to add customizations on out of box sites? How would you apply your customizations on multiple sites? The answer is Feature Stapling.

This article deals with various aspects of "Feature Stapling" in SharePoint 2010. We will see:

1. What Feature Stapling?

2. When to use Feature Stapling?

3. How to code Feature Stapling?

What is Feature Stapling?

Causes the attachment of a Feature to all new instances of sites that use a given site definition, without modifying the site definition or creating code routines to activate the Feature on each site. Also known as a feature site template association.

Real World Example

A developer creates a Feature and to add it to every new Web site that is based on a specific site definition. The developer creates a feature-stapling Feature that includes mappings between the Feature and site definition.
Technical Details

Feature stapling is implemented through a Feature that is specifically designed to staple other Features to one or more site definitions. Feature stapling allows a Feature to be stapled to any new sites created from any site definition or from specific site definitions based on the template name identified in the appropriate WEBTEMP.xml file.

Feature Stapling has two features. A "Stapler" feature which staples another feature to the site definition and the "Staplee" feature which will be stapled. Let's take an example to understand it. 

Scenario: You want to have custom list added to all of the "Team site" site definitions. This can be solved by creating a feature which will add the Custom list to the site and it can be associated with the Team site's site definition. 

How to associate feature with sites / site definition?

A Feature can be associated with the sites / site definition in three different ways:

1. You can create a site from that site definition and deploy your "custom list" feature to the site and activate it. 
2. If you already know all the required customizations before creating the site, you can include the features in the site definition (onet.xml) before you use it to create sites. 

3. If you want to automatically provision your feature when the user creates the site & you don't want to include it in the <SiteFeatures> or <WebFeatures> child elements of the <Configuration> element that represents the site definition configuration, you can use Feature Stapling. Another reason would be when you want to do customizations on out of the box site definitions, use of Feature Stapling.
1. This is self-explanatory 
2. Include the customization in site definitions. You can include the feature in the onet.xml file of site definition in <webfeatures> or <sitefeatures>. The section of the site definition which contains the web or site level features associated with it is shown below: 
  1. <Configuration ID="1" Name="Blank">  
  2.   <Lists />  
  3.   <Modules>  
  4.     <Module Name="DefaultBlank" />  
  5.   </Modules>  
  6.   <SiteFeatures>  
  7.     <!-- BasicWebParts Feature -->  
  8.     <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />  
  9.     <!-- Three-state Workflow Feature -->  
  10.     <Feature ID="FDE5D850-671E-4143-950A-87B473922DC7" />  
  11.   </SiteFeatures>  
  12.   <WebFeatures>  
  13.     <Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />  
  14.     <!-- TeamCollab Feature -->  
  15.     <Feature ID="F41CC668-37E5-4743-B4A8-74D1DB3FD8A4" />  
  16.     <!-- MobilityRedirect -->  
  17.   </WebFeatures>  
  18. </Configuration>  
  
Here the ID in the feature tag is the Feature ID/ GUID. The Sitefeatures tag has features which will be activated when this site definition is used to create a site collection, whereas, the Webfeatures tag has features which will be activated when this site definition is used to create a web.

3. Feature Stapling: Feature Stapling is achieved through the creation of another feature ("stapler") that defines the association of your regular Feature (the feature carrying your "Custom list") and the site definition you want to "staple" it too. In other words, you need to create two Features to achieve a complete Feature Stapling implementation. This means you can add your "Custom list" feature to all Team sites.
A step by step guide to making a Feature Stapling with OFTB blank site definition:

Scenario: I want a custom list instance named "Blog ListInstance" to be added to every site create using the blank site template. This scenario can be achieved using feature stapling. In the demo, I will be using Visual Studio 2010 with SharePoint 2010 for this example

Step 1: Create an Empty SharePoint project:
 

Step 2: Make it a farm solution
 

Step 3: Add a list definition to the project 
 

Step 4:  Select the type of the list definition and add a list instance for the list definition
 

Step 5: Update the element.xml which is in the same level as ListInstance1. Change TempalateType ="10001"
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
  4.   
  5.   <ListInstance Title="Blog - ListInstance1"  
  6.   
  7.                 OnQuickLaunch="TRUE"  
  8.   
  9.                 TemplateType="10001"  
  10.   
  11.                 Url="Lists/Blog-ListInstance1"  
  12.   
  13.                 Description="My List Instance">  
  14.   
  15.   </ListInstance>  
  16.   
  17. </Elements>  
Step 6: Make changes to element.xml which is in the same level of Blog(i.e. listdefinition), What we do here is
 

1. Add fields

2. Add Content type

3. Add fields to content type
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">    
  3.   <!-- Do not change the value of the Name attribute below. If it does not match the folder name of the List   
  4.        Definition project item, an error will occur when the project is run. -->    
  5.   <Field Type="Note"   
  6.          DisplayName="Description"   
  7.          Required="FALSE"   
  8.          NumLines="6"   
  9.          RichText="FALSE"   
  10.          Sortable="FALSE"   
  11.          ID="{cb55bba1-81a9-47b6-8e6c-6a7da1d25602}"   
  12.          StaticName="Blog Description"   
  13.          Name="Blog Description"   
  14.          Group="Custom Columns" />  
  15.   <Field Type="Text"   
  16.          DisplayName="Title"   
  17.          Required="FALSE"   
  18.          MaxLength="255"   
  19.          ID="{0248c82f-9136-4b3a-b802-d0b77280b3bc}"   
  20.          StaticName="BlogTitle"   
  21.          Name="BlogTitle"   
  22.          Group="Custom Columns" />  
  23.   <Field Type="Text"   
  24.          DisplayName="Writer"   
  25.          Required="FALSE"   
  26.          MaxLength="255"   
  27.          ID="{aa4a82dd-5b32-4507-9874-4e1c7bca3279}"   
  28.          StaticName="Writer"   
  29.          Name="Writer"   
  30.          Group="Custom Columns" />  
  31.     
  32.   <!-- content type-->  
  33.   <ContentType ID="0x010089E3E6DB8C9B4B3FBB980447E313CE94"    
  34.                Name="Blog Item"    
  35.                Group="Custom Content Types"   
  36.                Description="Blog item content type."    
  37.                Version="0">  
  38.     <!-- refer fields in the content type-->  
  39.     <FieldRefs>  
  40.       <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" />  
  41.       <FieldRef ID="{cb55bba1-81a9-47b6-8e6c-6a7da1d25602}" />  
  42.       <FieldRef ID="{0248c82f-9136-4b3a-b802-d0b77280b3bc}" />  
  43.       <FieldRef ID="{aa4a82dd-5b32-4507-9874-4e1c7bca3279}" />  
  44.     </FieldRefs>      
  45.   </ContentType>  
  46.     
  47.   <ListTemplate  
  48.     Name="Blog"  
  49.     Type="10001"  
  50.     DisallowContentTypes="FALSE"  
  51.     BaseType="0"  
  52.     OnQuickLaunch="TRUE"  
  53.     SecurityBits="11"  
  54.     Sequence="410"  
  55.     DisplayName="Blog"  
  56.     Description="My List Definition"  
  57.     Image="/_layouts/images/itgen.png"/>    
  58. </Elements>  

Step 7: Make changes to schema.xml to include content type, fields and View fields.
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <List xmlns:ows="Microsoft SharePoint" Title="MyFeatureStaplingDemo - Blog" 
  3. EnableContentTypes="TRUE" FolderCreation="FALSE" Direction="$Resources:Direction;" 
  4. Url="Lists/MyFeatureStaplingDemo-Blog" BaseType="0" 
  5. xmlns="http://schemas.microsoft.com/sharepoint/">  
  6.   <MetaData>  
  7.     <ContentTypes>  
  8.       <!-- mention content type-->  
  9.       <ContentTypeRef ID="0x010089E3E6DB8C9B4B3FBB980447E313CE94" />  
  10.       <ContentTypeRef ID="0x01">  
  11.         <Folder TargetName="Item" />  
  12.       </ContentTypeRef>  
  13.       <ContentTypeRef ID="0x0120" />  
  14.     </ContentTypes>  
  15.       
  16.     <Fields>  
  17.        <!--copy fiends in the content type-->  
  18.       <Field Type="Note"   
  19.              DisplayName="Description"   
  20.              Required="FALSE"   
  21.              NumLines="6"   
  22.              RichText="FALSE"   
  23.              Sortable="FALSE"   
  24.              ID="{cb55bba1-81a9-47b6-8e6c-6a7da1d25602}"   
  25.              StaticName="Blog Description"   
  26.              Name="Blog Description"   
  27.              Group="Custom Columns" />  
  28.       <Field Type="Text"   
  29.              DisplayName="Title"   
  30.              Required="FALSE"   
  31.              MaxLength="255"   
  32.              ID="{0248c82f-9136-4b3a-b802-d0b77280b3bc}"   
  33.              StaticName="BlogTitle" Name="BlogTitle"   
  34.              Group="Custom Columns" />  
  35.       <Field Type="Text" DisplayName="Writer"   
  36.              Required="FALSE" MaxLength="255"   
  37.              ID="{aa4a82dd-5b32-4507-9874-4e1c7bca3279}"   
  38.              StaticName="Writer" Name="Writer"   
  39.              Group="Custom Columns" />  
  40.     </Fields>  
  41.       
  42.     <Views>  
  43.       <View BaseViewID="0" Type="HTML" MobileView="TRUE" TabularView="FALSE">  
  44.         <Toolbar Type="Standard" />  
  45.         <XslLink Default="TRUE">main.xsl</XslLink>  
  46.         <RowLimit Paged="TRUE">30</RowLimit>  
  47.         <ViewFields>  
  48.           <!-- copy fields to the view-->  
  49.           <FieldRef Name="LinkTitleNoMenu"></FieldRef>  
  50.           <FieldRef Name="Attachments"></FieldRef>  
  51.           <FieldRef Name="LinkTitle"></FieldRef>  
  52.           <FieldRef Name="Blog Description"></FieldRef>  
  53.           <FieldRef Name="BlogTitle"></FieldRef>  
  54.           <FieldRef Name="Writer"></FieldRef>            
  55.         </ViewFields>  
  56.         <Query>  
  57.           <OrderBy>  
  58.             <FieldRef Name="Modified" Ascending="FALSE"></FieldRef>  
  59.           </OrderBy>  
  60.         </Query>  
  61.         <ParameterBindings>  
  62.           <ParameterBinding Name="AddNewAnnouncement" Location="Resource(wss,addnewitem)" />  
  63.           <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />  
  64.           <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_ONET_HOME)" />  
  65.         </ParameterBindings>  
  66.       </View>  
  67.       <View BaseViewID="1" Type="HTML" WebPartZoneID="Main"                          DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;" 
  68.         DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" 
  69.         SetupPath="pages\viewpage.aspx" ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">  
  70.         <Toolbar Type="Standard" />  
  71.         <XslLink Default="TRUE">main.xsl</XslLink>  
  72.         <RowLimit Paged="TRUE">30</RowLimit>  
  73.         <ViewFields>  
  74.           <FieldRef Name="Attachments"></FieldRef>  
  75.           <FieldRef Name="LinkTitle"></FieldRef>  
  76.           <!--copy fields to the view-->  
  77.           <FieldRef Name="Blog Description"></FieldRef>  
  78.           <FieldRef Name="BlogTitle"></FieldRef>  
  79.           <FieldRef Name="Writer"></FieldRef>  
  80.         </ViewFields>  
  81.         <Query>  
  82.           <OrderBy>  
  83.             <FieldRef Name="ID"></FieldRef>  
  84.           </OrderBy>  
  85.         </Query>  
  86.         <ParameterBindings>  
  87.           <ParameterBinding Name="NoAnnouncements" Location="Resource(wss,noXinviewofY_LIST)" />  
  88.           <ParameterBinding Name="NoAnnouncementsHowTo" Location="Resource(wss,noXinviewofY_DEFAULT)" />  
  89.         </ParameterBindings>  
  90.       </View>  
  91.     </Views>  
  92.     <Forms>  
  93.       <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />  
  94.       <Form Type="EditForm" Url="EditForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />  
  95.       <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />  
  96.     </Forms>  
  97.   </MetaData>  
  98. </List>  

Step 8: Deploy to SharePoint and you can see the Blog - ListInstance1 in the quick launch bar. This list definition and list instance feature should be web scoped. 
 

Stapling a feature to Site definition 

Step 1: Add an empty element to the project. Open element.xml and add the binding of feature to whatever site definition you wanted. 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
  3.   <!--this is stapling feature to Blank Site Tempaltes(STS#1)-->  
  4.   <FeatureSiteTemplateAssociation Id="099b30d7-6135-4b44-b1c8-20448d9e4b4b"   
  5.                                   TemplateName="STS#1" />  
  6. </Elements>  

Step 2: Create another feature scoping "farm" and add this element to it. 
 

Step 4: Create a site using blank site template and you are done. 
 

The solution looks like this: 
 
Hope this helps. Don't forget to leave a comment.

Ref: 
http://msdn.microsoft.com/en-us/library/bb861862(v=office.12).aspx
http://gallery.technet.microsoft.com/office/Feature-Stapling-in-fcbaf891
http://johanolivier.blogspot.in/2010/05/developing-list-definition-in.html