Creating a SharePoint 2010 Foundation MasterPage Solution and enable inheritance with Event Receivers.

As a consultant we very often need to develop a custom SharePoint 2010 solution which incorporates the customers company branding. There are a few ways to accomplish that and I will write down my preferred method in this blog post.

As the title of the blog states, this concerns a “Foundation” MasterPage solution, this is an important fact since SharePoint 2010 foundation MasterPages behave a little bit different then, for instance, a publishing MasterPage that you can use in SharePoint 2010 standard and enterprise. Inheritance of MasterPage settings is not an option in a Foundation environment!

Ok, lets start the magic!

Environment

For development and prototyping I have my own virtual machine configured with this software:

  • Windows server 2008 R2 standard – 64 bit
  • SQL Server 2008 R2
  • SharePoint 2010
  • Visual Studio
  • SharePoint Designer

    My virtual machine is configured without Active Directory and SharePoint 2010 uses local accounts to provide all Service Applications that I need.

    Here are some good blog posting on how to do that:

    Single Server Complete Install of SharePoint 2010 using local accounts

    Managed Accounts in SharePoint 2010

    Visual studio project

    Open up Visual Studio and create a new SharePoint project:

    Make sure you select “.NET Framework 3.5” type project!
    image

    Choose to what site you want to deploy your solution during test/debugging activities:

    The choice for a sandboxed or farm solution is up to you, most of the times I choose for a farm solution. In this case I am able to deploy a look and feel solution to multiple SiteCollections at once.

    image

    That’s it, you have created a SharePoint 2010 Visual Studio project.

    Choice

    An important decision you need to make before adding your MasterPage and stylesheets to the solution is where you want to deploy all the branding files, in the SharePoint content database or the the “layouts” folder on the file system. If you are creating a MasterPage solution for SharePoint 2010, deploying to the “layouts” folder is the best choice. It has a few advantages:

  • Performance – caching is a lot better when you deploy files to the “layouts” folder, rather then to the SharePoint content database. A blog post by Waldek Mastykarz on performance in SharePoint sites:

    How we did it: mavention.nl – Part 2: Performance

  • From within SharePoint 2010 Foundation MasterPages you can easily refer to a stylesheet that is in the “layouts” folder when you are in a subsite withing a SiteCollection, the relative path is always the same. Referring to the “Style Library” in SharePoint itself is a lot harder to keep it consistent and working on subsite levels.
  • In this blog post I will be using a combination.

    MasterPage

    Next, we are adding a module for our MasterPage:

    Right click on your project in the solution explorer and choose to create a new item, module.
    image

    Once you have done that, the new module is created and also a feature has been added to provision the module to SharePoint when you deploy the solution. You can rename that feature from “Feature1” to whatever you want! In my case: “DemoBlogPost”.

    image

    Feature

    You can delete the “sample.txt” from the MasterPage module and add your own custom MasterPage. That new custom file will automatically be added to the elements.xml. In my project I add some extra properties to the elements.xml so that it is available in SharePoint in the correct way:

    1 <?xml version="1.0" encoding="utf-8"?> 2 <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> 3 <Module Name="MasterPage" Url="_catalogs/masterpage"> 4 <File Path="MasterPage\demoblogpost.master" Url="demoblogpost.master" Type="GhostableInLibrary" 5 IgnoreIfAlreadyExists="false" > 6 <Property Name="ContentType" Value="$Resources:cmscore,contenttype_masterpage_name;" /> 7 <Property Name="UIVersion" Value="4" /> 8 </File> 9 </Module> 10 </Elements>

    Images and Stylesheets

    Now we need to make sure that the images and stylesheets that are used by the custom MasterPage are deployed by the solution, these files will be deployed to the “layouts” folder on the file system. Better performance and easy to use in the MasterPage.

    Refer from the MasterPage to your StyleSheet by adding a css registration line.

    <SharePoint:CssRegistration ID="CssRegistration" name="/_layouts/1033/styles/DemoBlogPost/demo.css" After="corev4.css" runat="server"/>

    Then right click on the project in the solution explorer, “Add new item” and choose for “SharePoint "Images Mapped Folder”

    image

    If you want to create a mapped folder for your stylesheets you need to choose for “SharePoint Mapped Folder”, you then get a new popup file browser window that starts from the “SharePoint Root” hyve. Browse to your preferred styles location, usually: “Template\Layouts\LCID(1033)\Styles\” and click “ok”.

    image

    The only thing you need to do now is: add your images to the “Images” mapped folder (create a subfolder name for the specific customer or project, in this case:, “DemoBlogPost”) and do the same for the “Styles” mapped folder.

    Your solution is ready to be deployed, that would upload your custom files to the SharePoint environment and make the feature available for activation in Site Collection Features.

    Once you have activated that feature you will still need to manually set your custom MasterPage as the default for the SharePoint site with for instance: SharePoint Designer. This is something you don’t want to be doing for a lot of subsites(if there are any/many) so that’s why I created two event handlers.

    Setting a custom MasterPage as the default for a SharePoint 2010 foundation site.

    In order to make sure that all existing SharePoint 2010 foundation sites get your new custom MasterPage with custom branding you need to add a event receiver to the feature that was created earlier in this blogpost. This will take care of setting your MasterPage as the default on all sites after activating the feature.

    Right click on the feature and select “Add event receiver”:

    imageimage

     

     

     

     

    An event receiver was created.

     

     

    By default the newly created event receiver is opened for editing in visual studio. We need to add some code to make sure that all existing sites get this MasterPage as the default.

    Everything beneath this line:

    1 public class DemoBlogPostEventReceiver : SPFeatureReceiver

    You can replace with:

    1 { 2 public override void FeatureActivated( 3 SPFeatureReceiverProperties properties) 4 { 5 SPSite siteCollection = properties.Feature.Parent as SPSite; 6 if (siteCollection != null) 7 { 8 SPWeb topLevelSite = siteCollection.RootWeb; 9 10 // Calculate relative path to site from Web Application root. 11 string WebAppRelativePath = topLevelSite.ServerRelativeUrl; 12 if (!WebAppRelativePath.EndsWith("/")) 13 { 14 WebAppRelativePath += "/"; 15 } 16 17 // Enumerate through each site and apply branding. 18 foreach (SPWeb site in siteCollection.AllWebs) 19 { 20 site.MasterUrl = WebAppRelativePath + 21 "_catalogs/masterpage/DemoBlogPost.master"; 22 site.CustomMasterUrl = WebAppRelativePath + 23 "_catalogs/masterpage/DemoBlogPost.master"; 24 site.Update(); 25 } 26 } 27 } 28 29 public override void FeatureDeactivating( 30 SPFeatureReceiverProperties properties) 31 { 32 SPSite siteCollection = properties.Feature.Parent as SPSite; 33 if (siteCollection != null) 34 { 35 SPWeb topLevelSite = siteCollection.RootWeb; 36 37 // Calculate relative path of site from Web Application root. 38 string WebAppRelativePath = topLevelSite.ServerRelativeUrl; 39 if (!WebAppRelativePath.EndsWith("/")) 40 { 41 WebAppRelativePath += "/"; 42 } 43 44 // Enumerate through each site and remove custom branding. 45 foreach (SPWeb site in siteCollection.AllWebs) 46 { 47 site.MasterUrl = WebAppRelativePath + 48 "_catalogs/masterpage/v4.master"; 49 site.CustomMasterUrl = WebAppRelativePath + 50 "_catalogs/masterpage/v4.master"; 51 site.AlternateCssUrl = ""; 52 site.SiteLogoUrl = ""; 53 site.Update(); 54 } 55 } 56 } 57 } 58 }

    Save the event receiver and close it! You can now test your solution by right clicking the project in the solution explorer and choose “Deploy”. Now the feature will be deployed to the SharePoint SiteCollection we have selected as the debugging SharePoint site, also it will be automatically activated.

    Have a look at your SharePoint site and notice that your custom MasterPage is now applied to all existing SharePoint sites and subsites for the selected SiteCollection.

    image

    Make sure that newly created SharePoint 2010 Foundation sites get the custom MasterPage

    We have allready created an event receiver to make sure that existing SharePoint 2010 foundation sites have the custom MasterPage applied. In a non SharePoint 2010 Foundation site you would normally have the option for all subsites to inherit the MasterPage from the parent, the Site Collection default. In Foundation there is no such option, you need to do that manually with SharePoint designer or with an event receiver, this is our way to go offcourse!

    Right click on the project in the solution explorer and select, “Add new item”.

    image

    Then choose for “Event Receiver” and give it a name, I have used an example that I have seen elsewhere on the internet: ”ChildSiteInit”. It’s clear what you use it for, good job! Glimlach

    image

    Now you will be prompted with settings you can select for the event receiver.

  • Choose “Web Events” at the type selection and
  • A site was provisioned

    Click “finish” and the event receiver will be created for you! Open up the “ChildSiteInit” event receiver and replace:

    1 base.WebProvisioned(properties);

    With:

    1 SPWeb childSite = properties.Web; 2 SPWeb topSite = childSite.Site.RootWeb; 3 childSite.MasterUrl = topSite.MasterUrl; 4 childSite.CustomMasterUrl = topSite.CustomMasterUrl; 5 childSite.Update();

    This small piece of code makes sure that new sites created within the current SiteCollection will automatically be updated with the MasterPage settings from the parent site.

    That’s it, you have created a SharePoint 2010 Foundation MasterPage Solution that automatically is applied to all existing and newly created sites within your preferred SiteCollection.

  • 13 thoughts on “Creating a SharePoint 2010 Foundation MasterPage Solution and enable inheritance with Event Receivers.

    1. Pingback: Tweets that mention Creating a SharePoint 2010 Foundation MasterPage Solution and enable inheritance with Event Receivers. « Rick Hilferink -- Topsy.com

    2. I followed the steps and i got the feature activated without any error.
      i tried various combination and by copying and pasting from the sample.master, v4.master and editing them.
      But it never shows a change in look and feel or anyhting!
      I am using Sharepoint 2010 Foundation and i copied all Styles and images from corresponding folders.

      But editing ..for eg. even if i delete a place holder ..no change is done on the site!!

      what could be wrong? any idea? i am using Visual studio 2010 ulti +sp foundation 2010 and my site has a site folder (/site/home.aspx ) any ideas???

      • Hi Zendil,

        Have you adjusted the line in the eventreceiver.cs:

        {
        20 site.MasterUrl = WebAppRelativePath +
        21 “_catalogs/masterpage/DemoBlogPost.master”;
        22 site.CustomMasterUrl = WebAppRelativePath +
        23 “_catalogs/masterpage/DemoBlogPost.master”;
        24 site.Update();
        25 }

        Where you need to adapt the “demoblogpost.master” with your own masterpage.

        If that is not the issue, you should check the following:

        – Is the MasterPage visible in the MP gallery
        – Is the StyleSheet reference from the MP correct
        – Are the image references from the StyleSheet correct

        Let me know if you managed to get it working or not, i am glad to be of help!

    3. Could you please tell me what is the scope …?
      Site right?
      But when i make Scope=”Site” i cann’t see it in feature list
      when i make Scope=”web” i can see it
      Both making no difference! NO REULT SO FAR
      And thats a bit of confusion(may be b’cos i’m feeling sleepy)
      When i create a site collection i get access to site features no site collection fetures are there..
      i just uploaded the activated and de avtivated feature screen shots here …just in case
      http://sharepoint2010foundation.blogspot.com/
      see..there is no difference….!!:(

      • You do know that when you set the scope for the feature to “Site” instead of “Web” that you need to activate it at “Site Collection Features” level. You should look 1 level higher then you are now i think, if you have full control and are farm admin, you should see “Site Collection Features” from Site Settings menu on the top level site.

        This feature is ment to apply at “Site Collection” level, all sites in the SC get your custom MasterPage when you follow the blogpost.

        I hope you can figure this out now.

    4. i got this error after i deploy the solution:
      Error occurred in deployment step ‘Activate Features’: The file or folder name “_catalogs” contains invalid characters. Please use a different name. Common invalid characters include the following: # % & * : ? / { | }
      can you advise how can i resolve it?

    5. When I add the child event receiver, I get the following error:

      ‘Operation is not valid due to the current state of the object’

      If I remove the child event receiver then the error goes away.

      Any ideas on the solution

    6. Hi,

      nice post. However, you say clearly that deploying master page to layouts in the best choice but you do the opposite in your sample?

      Thks

      • Hello Phil,

        Thanks and your totally right. I will make some small changes to the post.

        What I ment to say is, that deploying your branding files, css and images, to _layouts is the best choice in a performance point of view.

        However, deploying a MasterPage is a different story and the best way to go there is to deploy to _catalogs in SharePoint.

        Thanks again for pointing it out to me🙂

        Rick

    Geef een reactie

    Vul je gegevens in of klik op een icoon om in te loggen.

    WordPress.com logo

    Je reageert onder je WordPress.com account. Log uit / Bijwerken )

    Twitter-afbeelding

    Je reageert onder je Twitter account. Log uit / Bijwerken )

    Facebook foto

    Je reageert onder je Facebook account. Log uit / Bijwerken )

    Google+ photo

    Je reageert onder je Google+ account. Log uit / Bijwerken )

    Verbinden met %s