One .Master to Rule Them All (Two, actually)


One of the biggest annoyances with Sharepoint 2007 is the quirky things you have to do in order to customize a site.  This is especially true when it comes to custom master pages.  You create a stunning master page in Designer, configure the site to use it, then load the page and wait to bask in the glory. Lo and Behold!  It worked!  Job done, go grab a beer … but you better drink it fast because Sharepoint has a nasty surprise in store for you.  That master page only works on the content pages in your site.  System pages  (i.e. viewlists.aspx) will refuse to use your amazing Master page.  All that work is wasted on a half complete user experience.  Or is it?

Why is it not doing what I tell it to do?
This is because those system pages are hard-wired to use a different master page (application.master) .  To make matters worse, you only get one application.master for everywhere.  You could go modify this file, but be careful: changes to this will affect ALL pages based on that master, everywhere.   It’s not something that can be customized on a site-by-site basis.  To make matters still worse, Microsoft *will* update this file in upcoming patches, so odds are good that it will break on you sometime in the future, and likely with little warning.

Ok, so what’s the skinny?
Create a custom httpModule and install it on your Sharepoint site that remaps which .Master pages your pages use.  If you aren’t familiar with httpModules, fear not, they are extremely simple.

The httpModule sits in the middle of the http request processing stream and can intercept page events when they initialize.  The pages load up and say “I’m going to use application.master”, to which your module replies “not on my watch, buddy” and not so gently forces the page to use the Master page of your choice.

The Gory Details
(this assumes that you already have the aforementioned Nifty Master Page created.  If not, please search Google for any of the hundreds of tutorials on how to do this)

Prepare your Master Pages
You will need two .Master pages.  One to replace default.master and the other to replace application.master.  It is very important that when you are creating these pages that you include all of the ContentPlaceHolders that exist in the .Master page you are replacing.    Throw any ContentPlaceHolders that you are not using in a hidden DIV at the bottom of the page – but before the closing FORM tag (the only exception to this seems to be “PlaceHolderUtilityContent” which goes in after the closing form tag).  Once in place, you can use the normal Master Page options in the UI to select the default.master replacement.

Second, be sure to remove the Search Control from your Application.Master replacement.  The reason for this is that the search box does not normally appear on system pages and will cause an error during rendering.

You can probably simplify this a bit by using nested master pages, but I haven’t had a chance to look into that yet.

Step 1 – Create the httpModule
Create a new Class Library project in Visual Studio and start with the code below.  So simple, even a manager could do it (maybe).  Obviously, you will have to change the path to match your environment.  Oh, and sign the assembly as well.

Note the path above: that is required so that all pages can find the Master page as not all pages are running from the site context

This is a simplified example but you can see the potential here.  With this in place, YOU control the horizontal and YOU control the vertical.  Or, for a more modern reference, YOU decide who gets the red pill and who gets the blue pill.

Build it and then throw the DLL in the /bin folder in your SharePoint site root (usually something like InetpubwwwrootwssVirtualDirectories80in).  You may have to create the in folder if one is not there.  Once you have it working the way you want, you will need to sign it and move it to the GAC, but this works for getting started.

Step 2 – Register the httpModule
Another easy step – throw in the bolded line below in your web.config file at the bottom of the httpModules section.  This section should already be there.


<httpModules>
… stuff you dont care about …
<addname=“MyHandlerTest“type=“MasterPageModule, MasterPageHandlerModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6bdb1331dfc11306“/>
</httpModules>

Step 3 – Load the Page
Navigate to the home page of your site.  That should work normal as it is using the normal Sharepoint Master page logic.  Now go to a System page, like ‘Documents’ , ‘Lists’ or ‘Pictures’.  These should now be using your Master page

If you’ve followed the this tip you will actually be able to see the real error, if any, when you load the page.

Step 4 – Go get that beer
Do you really need instructions for this?

Special  thanks to K. Scott Allen for his post showing how to change the .Master page using an httpModule.  You will notice that the code above bears an amazing resemblance to his.

3/1/2007 – UPDATE!
In response to comments, I have updated these instructions, in particular, I have added the “Prepare your Master Pages” section that addresses most of the issues encountered in the comments.

Also, do not use this method if your SharePoint install has the shared Service Provider (SSP) installed on the same web application as your main SharePoint environment.  The system pages used by the SSP do not work properly when their master page is replaced like this.  I’m sure there is a logical reason why, I simply haven’t had the time to dive into it.

Advertisements

Posted on January 8, 2007, in SharePoint and tagged , . Bookmark the permalink. 9 Comments.

  1. this code throwing following error.

    MasterPage cannot be applied to this page because the control collection is read-only. If the page contains code blocks, make sure they are placed inside content controls (i.e. ) at System.Web.UI.MasterPage.CreateMaster(TemplateControl owner, HttpContext context, VirtualPath masterPageFile, IDictionary contentTemplateCollection)
    at System.Web.UI.Page.get_Master()
    at System.Web.UI.Page.ApplyMasterPage()
    at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

  2. Not sure what you are seeing but it sounds like you are trying to put the code in the master page directly, which is not where it goes. You need to create a separate assembly

    • I didn’t write any inline code.I am getting this error even i try to give MasterPageFile as default.master.

      • What does it do if you attempt to use one of the out of the box master pages, such as BlueBand.master?

      • Eventhrough we used the blueband.master it is giving same error.
        We are trying to use the http handler to change the master pages for dynamically.

      • The same error showing up even with oob master page(BlueBand.master).
        Note, here i am using form based authentication.

  3. I copied the signed DLL to the GAC and the bin folder in my root site. But SharePoint complaints about this.

    Could not load file or assembly ‘MasterPageHandlerModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6bdb1331dfc11306’ or one of its dependencies. The system cannot find the file specified. (C:\Inetpub\wwwroot\wss\VirtualDirectories\2003\web.config line 129

    Line 129:

  4. When I do this, it works for the search results, etc. but if I go to the site settings admin page, it gives me a sharepoint error page and says an unknown error has occured. Have you seen this happen?

  1. Pingback: application.master and SharePoint Application Page Branding | Furuknap's SharePoint Corner

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s