It’s very common to need to apply a custom master page to your SharePoint site. Very frequently you need to apply your custom master page to all sites within your site collection. And perhaps you’ll even need to apply your master page to all the site collections contained within all your web applications operating within a farm. This is easy enough to accomplish when you are customizing a site for the first time, since most subwebs are set up to inherit from their parent site, so if you customize the parent site, it will apply to all the children. But what happens when a site collection has already been operational, and you want to create a new custom page that applies to all the children sites, even if someone has said they didn’t want to inherit from the parent site? Furthermore, what happens when you deactivate the feature? By deactivating the feature does that mean that you have to reset all the sites back to the “default.master” master page, thereby erasing all the customizations people had made? I have seen a number of articles out there about creating a custom master page and installing it as a feature, but I wanted to take it a step further and write code that will handle applying the master page to all children sites, as well as insuring that the feature could be successfully uninstalled and revert all the sites back to their original master page. (Only if the originally set master page can’t be found will it revert the site to the default.master page.)

Before we begin, the first thing is to note the use of SPWeb.MasterUrl and SPWeb.CustomMasterUrl. A fairly good explanation of the meaning of these two properties can be found on Jim Yang’s blog on SharePointBlogs.com: http://www.sharepointblogs.com/jimyang/archive/2006/07/09/moss-2007-and-wss-3-0-master-page.aspx. Secondly, there’s a good post about creating a feature that installs a custom master page on Paul Papanek’s blog, at http://mindsharpblogs.com/PaulS/archive/2007/06/18/1903.aspx.

OK… on to the code. The first step is to create your SharePoint Visual Studio project to build a feature solution package. To see how to do this, read my blog entry E-mailing a Document from a SharePoint Document Library. Go ahead and create the project, name it GlobalMasterPage, modify its XMl file to create the wsp and cab files, dd the .ddf and .Targets file, and create a key to digitally sign the project. Last but not least, create your feature folder called GlobalMasterPage. Wasn’t that easy? Moving on….

Create a new file inside your TEMPLATE\FEATURES\GlobalMasterTemplate folder and call it MyCustom.master. Go ahead and create the custom master page you want from within SharePoint Designer, then copy and paste the markup into your Visual Studio master page, or else just copy the contents of default.master in the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATES\GLOBAL directory on your drive. Note: don’t open up the default.master page from the GLOBAL directory in SharePoint Designer; that file is very important to SharePoint and SPD might modify its contents.) Also, create a preview image (which the user will see when they try to select the master page within the SharePoint browser UI), and call it CutomizedMasterPreview.gif, and place it inside the GlobalMasterPage folder as well.

OK, now create a file called elements.xml inside your GlobalMasterTemplate folder. Add the following XML:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Module Url="_catalogs/masterpage" RootWebOnly="TRUE">
    <File Url="MyCustom.master"
      Name="MyCustom.master"
      Type="GhostableInLibrary"
      IgnoreIfAlreadyExists="FALSE">
      <Property Name="ContentType" Value="$Resources:cmscore,contenttype_masterpage_name;"/>
      <Property Name="PublishingPreviewImage" 
        Value="~SiteCollection/_catalogs/masterpage/Preview Images/Custom/CustomizedMasterPreview.gif, 
        ~SiteCollection/_catalogs/masterpage/Preview Images/Custom/CustomizedMasterPreview.gif" />
      <Property Name="Title" Value="MyCustom.master" />
    </File>
  </Module>
  <Module Url="_catalogs/masterpage/Preview Images/Custom" RootWebOnly="TRUE">
    <File Url="CustomizedMasterPreview.gif" Name="CustomizedMasterPreview.gif" Type="GhostableInLibrary">
      <Property Name="Title" Value="CustomizedMasterPreview.gif" />
    </File>
  </Module>
</Elements>

If we take a look at what it’s doing, it’s adding a page called MyCustom.master to the /_catalogs/masterpage folder. We’re assigning it three values: a Content Type, a preview image, and a Name. The next thing we’re doing is adding a file to a folder called “Custom”, within the “Preview Images” folder. (If the folder doesn’t already exist, it will be created.) We’re giving that file a Name property as well.