Mar 19, 2014

Discard AppWebs When Setting Custom MasterPages

I have long used a feature event receiver to set MasterPages throughout the webs (i.e. sites) in a site collection when my branding feature is activated, and also an inheritance event receiver to set the MasterPage for any new web when it has been provisioned. In SharePoint 2010, search sites required a different MasterPage than the rest of the sites, so in the code of the receivers, this was always taken into consideration, as you can see in the article linked above. In 2013, this is unnecessary as the same MasterPage goes for all sites, so I have used the simplified version of the receiver code, with no webtemplateid checks.

Or, so I thought. Turned out, my testing had been lacking, since I do not use apps in my development&test environment, and thus it had not occured to me, that the app webs (which I sort of assumed to be separate, but apparently are not) respond to these event receivers too. As tests proved, my receivers actually "broke the SharePoint" when appwebs were involved. So, a little improvement to both receivers here, checking that a web is not an appweb (APP#0, WebTemplateId == 17) before making any MasterPage changes:

Feature event receiver, activate feature:

SPSite site = properties.Feature.Parent as SPSite;
            if (site != null)
            {
                SPWeb topLevelSite = site.RootWeb;
                string WebAppRelativePath = topLevelSite.ServerRelativeUrl;

                if (!WebAppRelativePath.EndsWith("/"))
                {
                    WebAppRelativePath += "/";
                }

                foreach (SPWeb web in site.AllWebs)
                {
                    if (web.WebTemplateId != 17)
                    {
                        web.MasterUrl = WebAppRelativePath + "_catalogs/masterpage/mycustommaster.2013.masterpage.master";
                        web.CustomMasterUrl = WebAppRelativePath + "_catalogs/masterpage/mycustommaster.2013.masterpage.master";
                        web.Update();
                    }

                }
            }

Event receiver, web provisioned:

SPWeb newWeb = properties.Web;
            SPWeb topSite = newWeb.Site.RootWeb;
            if (newWeb.WebTemplateId != 17)
            {
                newWeb.MasterUrl = topSite.MasterUrl;
                newWeb.CustomMasterUrl = topSite.CustomMasterUrl;
                newWeb.Update();
            }
        }

For the sake of consistency, I also fixed the deactivate feature code to leave the appwebs alone.

No comments: