Olav Aukan Getting information off the Internet is like taking a drink from a fire hydrant…

19Feb/10

How to automatically set the master page when a site is created

So you've created an awesome master page for your team sites but you are a bit annoyed that you have to manually configure every new site to use this master page after they are created. Perhaps some of the users forget to do this and then you end up with different branding on different sites leading to more confusion. Wouldn't it be nice if we could apply our custom master page automatically upon creation of a team site? With the wonders of feature stapling this can be done quite easily.

Feature stapling is basically a way of attaching a (custom) feature to a site template without modifying the site template itself so that when a site is created from that template the stapled feature is automatically activated. In this example we will staple our feature to the Team Site template. The steps involved are:

  1. Create a new Visual Studio project for our features.
  2. Create the Team Site Master Page Activator feature that sets our custom master page for new sites.
  3. Create the Team Site Master Page Stapler feature that staples our activator feature to the Team Site template.
  4. Deploy WSP

First of all, get WSPBuilder if you are not already using it. WSPBuilder integrates right into Visual Studio and lets you build WSP packages from your solution with just a few clicks. If you are developing locally on a SharePoint server it can handle the deployment for you as well. I'm not gonna go into details on how wonderful this tool is so you're just gonna have to take my word for it.

1. Create a new Visual Studio project

WSPBuilder will add new project types to Visual Studio, so fire it up and create a "WSPBuilder Project". I'm using VS2008 in this example.

2. Create the Team Site Master Page Activator feature

After the project is created, we can start adding features to the project. We'll start with the activator feature which handles activating and deactivating our custom master page. Add the feature to the project by clicking Add -> New Item and selecting the WSPBuilder item "Feature with receiver".

Give the feature the name "TeamSiteMasterPageActivator" and click Add. This brings up the Feature Settings window.

Make sure the scope is set to Web, give the feature a description and click OK.

WSPBuilder will generate a Feature.xml file similar to this:

<?xml version="1.0" encoding="utf-8"?>
<Feature  Id="83f0030d-3921-485c-99d9-49d205d86d79"
          Title="Team Site Master Page Activator"
          Description="This feature set's the master page of a team site to our 'CustomTeamSite.master'."
          Version="12.0.0.0"
          Hidden="FALSE"
          Scope="Web"
          DefaultResourceFile="core"
          ReceiverAssembly="MasterPageActivator, Version=1.0.0.0, Culture=neutral, PublicKeyToken=978fbee28dd41158"
          ReceiverClass="MasterPageActivator.TeamSiteMasterPageActivator"
          xmlns="http://schemas.microsoft.com/sharepoint/">
  <ElementManifests>
    <ElementManifest Location="elements.xml"/>
  </ElementManifests>
</Feature>

In this post I am assuming you've already deployed you custom master page with a different solution. In the future I'll post a guide on how to package and deploy master pages with WSPBuilder, but for now let's just assume there's a 'CustomTeamSite.master' in the site collection master page gallery. We can now edit the feature receiver code to make it set our custom master page when the feature is activated. This is done in the FeatureActivated method. Our end result should look something like this:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
    try
    {
        using (SPWeb currentWeb = properties.Feature.Parent as SPWeb)
        {
            using (SPSite currentSite = currentWeb.Site)
            {
                string masterPageUrl = string.Format("{0}/_catalogs/masterpage/CustomTeamSite.master", currentSite.ServerRelativeUrl).Replace("//", "/");
                currentWeb.CustomMasterUrl = masterPageUrl;
                currentWeb.MasterUrl = masterPageUrl;
                currentWeb.Update();
            }
        }
    }
    catch (Exception ex)
    {
        string errorMessage = string.Format("An exception occured while trying to activate the feature. Message: '{0}'.", ex.Message);
        throw new SPException(errorMessage);
    }
}

We probably want our feature to clean up after itself when it's deactivated, so we'll go ahead and add some code to the FeatureDeactivating method that sets the site's master page back to 'default.master'. The code looks something like this:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    try
    {
        using (SPWeb currentWeb = properties.Feature.Parent as SPWeb)
        {
            using (SPSite currentSite = currentWeb.Site)
            {
                string masterPageUrl = string.Format("{0}/_catalogs/masterpage/default.master", currentSite.ServerRelativeUrl).Replace("//", "/");
                currentWeb.CustomMasterUrl = masterPageUrl;
                currentWeb.MasterUrl = masterPageUrl;
                currentWeb.Update();
            }
        }
    }
    catch (Exception ex)
    {
        string errorMessage = string.Format("An exception occured while trying to deactivate the feature. Message: '{0}'.", ex.Message);
        throw new SPException(errorMessage);
    }
}

3. Create the Team Site Master Page Stapler feature

The activator feature is now done and we can move on to the stapler feature. Add the feature to the project by clicking Add -> New Item and selecting the WSPBuilder item "Blank Feature".

Give the feature the name "TeamSiteMasterPageStapler" and click Add. This brings up the Feature Settings window.

Make sure the scope is set to Farm, give the feature a description and click OK.

WSPBuilder will generate a Feature.xml file similar to this:

<?xml version="1.0" encoding="utf-8"?>
<Feature  Id="1cd9b76d-1915-44ef-b704-3307d53fab65"
          Title="Team Site Master Page Stapler"
          Description="This feature staples the 'Team Site Master Page Activator' feature to the Team Site template so that it's activated when a new team site is created."
          Version="12.0.0.0"
          Hidden="FALSE"
          Scope="Farm"
          DefaultResourceFile="core"
          xmlns="http://schemas.microsoft.com/sharepoint/">
  <ElementManifests>
    <ElementManifest Location="elements.xml"/>
  </ElementManifests>
</Feature>

Next we need to create a FeatureSiteTemplateAssociation node in the Elements.xml file that staples this feature to the built-in Team Site template. For this we need the GUID of our custom feature and the TemplateName of the Team Site template. For a list of valid TemplateNames check out this blog. We want to staple our feature to the Team Site template, so we will use the TemplateName 'STS#0'. The modified Elements.xml looks like this.

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <FeatureSiteTemplateAssociation Id="83f0030d-3921-485c-99d9-49d205d86d79" TemplateName="STS#0"/>
</Elements>

The Visual Studio project should now look something like this.

4. Deploy WSP

The stapler feature is now complete and we can deploy the solution. If you are working on a SharePoint server all you have to do is right-click on the solution and select WSPBuilder -> Build WSP and then WSPBuilder -> Deploy. If you are not working on a SharePoint server you will have to copy the WSP file and installation script generated by WSPBuilder to the SharePoint server and deploy it using the script. Once the solution has been deployed you can test that it works by creating a new site from the Team Site template. The new site should now have your 'CustomTeamSite.master' applied.

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

Any sample code on this blog is provided "AS IS”, without warranty of any kind. The author takes no responsibility for problems arising from the use of this code.