Deploying and applying a master page as a feature
Keeping on with my run of posts about stuff that can be done with features, here is the latest thing I have done. The scenario this time is that we want to have a feature that will not only deploy a masterpage when it is activated, but we want to set it as the current masterpage for the site as well. So first thing is first, go and make yourself an appropriate masterpage, then put your feature together. Here is an example what my feature looks like
Feature.xml
<?xml version="1.0" encoding="utf-8"?>
<Feature Id="b6721f55-d5a7-48f4-abca-46a1633ad596"
Title="My New Master Page"
Description="Deploys and uses a new master page"
Version="12.0.0.0"
Hidden="FALSE"
Scope="Web"
DefaultResourceFile="core"
ReceiverAssembly="dll_name, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PublicKey"
ReceiverClass="Namespace.ClassName"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
<ElementFile Location="MyCustom.master" />
</ElementManifests>
</Feature>
<Feature Id="b6721f55-d5a7-48f4-abca-46a1633ad596"
Title="My New Master Page"
Description="Deploys and uses a new master page"
Version="12.0.0.0"
Hidden="FALSE"
Scope="Web"
DefaultResourceFile="core"
ReceiverAssembly="dll_name, Version=1.0.0.0, Culture=neutral, PublicKeyToken=PublicKey"
ReceiverClass="Namespace.ClassName"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
<ElementFile Location="MyCustom.master" />
</ElementManifests>
</Feature>
Elements.xml
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="CustomMaster" Url="_catalogs/masterpage">
<File Url="MyCustom.master" Type="GhostableInLibrary" >
<Property Name="ContentType" Value="My Custom master page" />
<Property Name="MasterPageDescription" Value="This is my custom master page" />
<Property Name="Title" Value="MyCustom.master" />
</File>
</Module>
</Elements>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="CustomMaster" Url="_catalogs/masterpage">
<File Url="MyCustom.master" Type="GhostableInLibrary" >
<Property Name="ContentType" Value="My Custom master page" />
<Property Name="MasterPageDescription" Value="This is my custom master page" />
<Property Name="Title" Value="MyCustom.master" />
</File>
</Module>
</Elements>
receiver.cs
/// <summary>
/// Applies the custom master page to the site
/// </summary>
/// <param name="properties"></param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
web.AllProperties["OldMasterUrl"] = web.MasterUrl;
web.AllProperties["OldCustomMasterUrl"] = web.CustomMasterUrl;
web.MasterUrl = web.ServerRelativeUrl + "/_catalogs/masterpage/MyCustom.master";
web.CustomMasterUrl = web.ServerRelativeUrl + "/_catalogs/masterpage/MyCustom.master";
web.Update();
}
/// Applies the custom master page to the site
/// </summary>
/// <param name="properties"></param>
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
web.AllProperties["OldMasterUrl"] = web.MasterUrl;
web.AllProperties["OldCustomMasterUrl"] = web.CustomMasterUrl;
web.MasterUrl = web.ServerRelativeUrl + "/_catalogs/masterpage/MyCustom.master";
web.CustomMasterUrl = web.ServerRelativeUrl + "/_catalogs/masterpage/MyCustom.master";
web.Update();
}
/// <summary>
/// Restores the original masterpage that was on the site when this feature was activated
/// </summary>
/// <param name="properties"></param>
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
web.MasterUrl = web.AllProperties["OldMasterUrl"];
web.CustomMasterUrl = web.AllProperties["OldCustomMasterUrl"];
web.Update();
}
/// Restores the original masterpage that was on the site when this feature was activated
/// </summary>
/// <param name="properties"></param>
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
web.MasterUrl = web.AllProperties["OldMasterUrl"];
web.CustomMasterUrl = web.AllProperties["OldCustomMasterUrl"];
web.Update();
}
OK, so lets go over what is here. In the feature.xml file, just make sure that you add your master page as an elements file. Then in elements.xml we are defining a module that is used to deploy a file – we specify the URL that it is deployed to, which is relative to where the feature is being activated, which is any given site in a site collection in this instance as the feature’s scope is set to ‘web’. We add a file attribute to the module, telling SharePoint to take our mycustom.master page and put it there, and we set some properties of the file. We give it a name (which goes in the contenttype attribute), description and set the title to be the name of the file.
Now comes the cool bit – in feature.xml we specified a reciever, which is a class with code that will run when the feature is actived/deactived etc. (Now that I think about it, I don’t think that I have mentioned that I set up my features using WSP builder and Visual Studio – very very easy way to do things, just chosoe to add a new item in VS and select efature with receiver, and it will add the appropriate class and XML for you). In the reciever we are adding code that sets the main master page, and the custom master page attributes of the site. We also store the existing values as site properties that can be retrieved in the feature deactivating event so we can restore the original state of the site when the feature is deactivated. Bundle that up into a solution, deploy it and then you can deploy your master page where ever you want.
You could even take this code further by having it scan through sub sites and applying the master page to all subsites. Then you can apply the same master page to a section of a site collection – Much easier than deploying and setting masterpages through the UI.



