Custom Master Pages in SharePoint without Publishing Features

March 23 2012

Posted 17:30 | by Ben Duguid - zhaph | Perma-link

There are a number of useful blog posts out there that talk about applying Custom Master Pages to SharePoint Team Sites, Blogs, etc., and some, like Bugra Postaci's post, even use stapling to do this automatically.

However, at the end of the day, they all have one thing in common: They claim you need to activate the Publishing Features to do this, even when you're doing it programmatically.

Assigning custom Master Pages to Out-of-the-Box SharePoint sites without activating Publishing Features

Obviously this all needs to happen within a SharePoint project, and assumes that you've created a customised Master Page in your Master Page Gallery.

Starting from a Blank SharePoint project, that is set to "Deploy as a Farm Solution" I added a new feature, and scoped it to the "Web - Activates a Feature for a specific web site.":

A new fearure with the scope set to Web

Right-click on the feature in the solution explorer, and add an event receiver:

Add Event Receiver

Implement the FeatureActivated method (note that we're also setting the Site Master as well as the System Master, that way if the Publishing Features are enabled later they will be set correctly):

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
  // Get the SPWeb we're being activated in.
  var web = (SPWeb)properties.Feature.Parent;

  if (null != web) {
    // Get the Site Collection root path to get the master page gallery.
    string siteCollectionRoot = web.Site.RootWeb.Url;

    // Set the Site Master to Custom.master
    var siteMaster = new Uri(siteCollectionRoot +
                             "/_catalogs/masterpage/" +
                             "Custom.Master");
    web.CustomMasterUrl = siteMaster.AbsolutePath;

    // Set the System Master to Custom.master
    var systemMaster = new Uri(siteCollectionRoot +
                               "/_catalogs/masterpage/" +
                               "Custom.Master");
    web.MasterUrl = systemMaster.AbsolutePath;

    // Clear the Alternate CSS
    web.AlternateCssUrl = string.Empty;

    // Save the changes back to the web
    web.Update();
  }
}

And FeatureDeactivating to set things back to the default master page:

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
  // Get the SPWeb we're being activated in.
  var web = (SPWeb)properties.Feature.Parent;

  if (null != web) {
    // Get the Site Collection root path to get the master page gallery.
    string siteCollectionRoot = web.Site.RootWeb.Url;

    // Set both Master Pages to v4.master
    var siteMaster = new Uri(siteCollectionRoot +
                             "/_catalogs/masterpage/" +
                             "v4.master");
    web.CustomMasterUrl = siteMaster.AbsolutePath;
    web.MasterUrl = systemMaster.AbsolutePath;

    // Clear the Alternate CSS
    web.AlternateCssUrl = string.Empty;

    // Save the changes back to the web
    web.Update();
  }
}

All fairly simple so far, and once you've deployed this feature, you can activate it and it will apply your custom master pages to you team sites. As you've hopefully already guessed, these are based on the "System Master Page" - so you really need to ensure that your template is left aligned and fluid - there's a whole other post hidden in that statement I'm sure.

Automatically assigning Custom Master pages on new sites as they are created

Create another feature in your project, and this time scope it to at least "Site - Activates a Feature for all web sites in a site collection", however your milage may vary, and will depend on the setup of your Farm - if you have multiple Web Applications that don't all have this branding applied to them, then you don't want to be scoping this at the Farm level. If the majority of your Web Applications share the same branding scoping it to WebApplication and deactivating it on those Web Applications that don't use the branding might suffice.

Next, add a new "Empty Element" to the project:

New Empty Element

First, open the CustomMasterPages feature, and switch to the "Manifest" view to find the id of the feature:

Switch to Feature Manifest view

Then in the Elements.xml add the details of the features you want to activate:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <FeatureSiteTemplateAssociation Id="e5f2c515-d45f-4096-a0b1-7d486a4d011a"
                        TemplateName="GLOBAL" />
</Elements>

As you can see, no Publishing Features were harmed in the making of this feature. I've set this to apply my custom Master Pages to every site template so that the users have a nice consistent branding throughout their Intranet - however you can pick and choose which ones you want here, or you could do it in code during the feature activation if (for example) you want to apply a different Master Page to the Blog Site template.

Then in the stapling feature, add the Element:

Add the Elements to the Feature

Save, deploy and test. You should now have your custom master pages in action every time you create a new site within SharePoint.

Filed under: SharePoint