I've got a WebApplication which should contain a publishing site collection and a custom masterpage for that site collection. I wanted to achieve, if this site collection is created during deployment, the custom masterpage should be automatically applied
to it. So the following subsites, that will be created after that during deployment, will automatically inherit the masterpage of the site collection on creation. (error at the bottom of the question ;) )
I tried to create a feature stapling. So I created a feature called PortalMasterPageStapler.featureand set the scope to WebApplication.
After that I created an empty element called PortalMasterStapler and inside the Elements.xml
<?xml version="1.0" encoding="utf-8"?><Elements xmlns="http://schemas.microsoft.com/sharepoint/"><FeatureSiteTemplateAssociation Id="8e0965b6-2128-44d9-bcf6-98fc3b1cac98" TemplateName="CMSPUBLISHING#0" /></Elements>
I've got a module called PortalMaster (inside a folder "Modules") including the masterpagesPortal.master and PortalSystem.master. It also includes an Elements.xml (at the moment it also includes another masterpage, but I wanted to test the feature with just one masterpage, first).
<?xml version="1.0" encoding="utf-8"?><Elements xmlns="http://schemas.microsoft.com/sharepoint/"><Module Name="PortalMaster" List="116" Url="_catalogs/masterpage" Path="PortalMaster" RootWebOnly ="false"><File Path="PortalMaster\Portal.master" Url="Portal.master" IgnoreIfAlreadyExists="TRUE" Type="GhostableInLibrary"><Property Name="UIVersion" Value="4" /><Property Name="ContentTypeId" Value="0x010105" /><Property Name="Title" Value="Jasmin Publishing Master Page (Portal)" /></File><File Path="PortalMaster\PortalSystem.master" Url="PortalSystem.master" IgnoreIfAlreadyExists="TRUE" Type="GhostableInLibrary"><Property Name="UIVersion" Value="4" /><Property Name="ContentTypeId" Value="0x010105" /><Property Name="Title" Value="Jasmin Publishing System Master Page (Portal)" /></File></Module></Elements>
Then there's the feature PortalMasterProvisioning for the masterpage activation itself with an event receiver (set to scope site):
using System; using System.Runtime.InteropServices; using System.Security.Permissions; using Microsoft.SharePoint; using Microsoft.SharePoint.Security; namespace abc.MasterPages.Features.PortalMasterProvisioning { /// <summary> /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade. /// </summary> /// <remarks> /// The GUID attached to this class may be used during packaging and should not be modified. /// </remarks> [Guid("f6224605-7edf-42cf-9eef-c2a5159fee21")] public class PortalMasterProvisioningEventReceiver : SPFeatureReceiver { // Uncomment the method below to handle the event raised after a feature has been activated. public override void FeatureActivated(SPFeatureReceiverProperties properties) { try { using (SPWeb web = properties.Feature.Parent as SPWeb) { using (SPSite site = web.Site) { string masterPageUrl = string.Format("{0}/_catalogs/masterpage/Portal.master", site.ServerRelativeUrl.Replace("//", "/")); web.CustomMasterUrl = masterPageUrl; web.MasterUrl = masterPageUrl; web.Update(); } } } catch (Exception ex) { string errorMessage = string.Format("Error at activation of feature: {0}", ex.Message); throw new SPException(errorMessage); } } // Uncomment the method below to handle the event raised before a feature is deactivated. public override void FeatureDeactivating(SPFeatureReceiverProperties properties) { try { using (SPWeb web = properties.Feature.Parent as SPWeb) { using (SPSite site = web.Site) { string masterPageUrl = string.Format("{0}/_catalogs/masterpage/v4.master", site.ServerRelativeUrl.Replace("//", "/")); web.CustomMasterUrl = masterPageUrl; web.MasterUrl = masterPageUrl; web.Update(); } } } catch (Exception ex) { string errorMessage = string.Format("Error at activation of feature: {0}", ex.Message); throw new SPException(errorMessage); } } }
And here's the event receiver to apply the masterpage to the childsites:
using System; using System.Security.Permissions; using Microsoft.SharePoint; using Microsoft.SharePoint.Security; using Microsoft.SharePoint.Utilities; using Microsoft.SharePoint.Workflow; using System.IO; using System.Linq; namespace abc.MasterPages.ChildSiteInit { /// <summary> /// Web Events /// </summary> public class ChildSiteInit : SPWebEventReceiver { //Search Template IDs private static readonly Int32[] SearchTemplatesIds = { (Int32)WebTemplateId.BasicSearchCenter, (Int32)WebTemplateId.EnterpriseSearchCenter, (Int32)WebTemplateId.FastSearchCenter }; /// <summary> /// A site was provisioned. /// </summary> public override void WebProvisioned(SPWebEventProperties properties) { SPWeb childSite = properties.Web; SPWeb topSite = childSite.Site.RootWeb; //set Search Master if (SearchTemplatesIds.Contains(childSite.WebTemplateId)) { childSite.MasterUrl = "/_catalogs/masterpage/Search.master"; childSite.CustomMasterUrl = childSite.MasterUrl; childSite.AlternateCssUrl = ""; } else { childSite.MasterUrl = topSite.MasterUrl; childSite.CustomMasterUrl = topSite.CustomMasterUrl; childSite.AlternateCssUrl = topSite.AlternateCssUrl; childSite.SiteLogoUrl = topSite.SiteLogoUrl; childSite.Update(); } } } }
But when I try to deploy the WSP, I get this error:
Install-SPSolution : Failed to create receiver object from assembly "abc.MasterPages, Version=0.0.0.0, C ulture=neutral, PublicKeyToken=0bc15e792b3fcfaf", class "$SharePoint.Type.f6224605-7edf- 42cf-9eef-c2a5159fee21.FullName $" for feature "abc.MasterPages_PortalMasterProvisioning" (ID: bd6aee09-9381-4f66-9997- 23bd2a3dfc4c).: S ystem.ArgumentNullException: Value cannot be null. Parameter name: type at System.Activator.CreateInstance(Type type, Boolean nonPublic) at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject() At line:1 char:19+ Install-SPSolution <<<< -Identity abc.masterpages.wsp -GACDeployment -Local+ CategoryInfo : InvalidData: (Microsoft.Share...InstallSolution:SPCmdletInstallSolution) [Install-SPSolu tion], InvalidOperationException+ FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletInstallSolution