SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

Centralize Master page and Alternate CSS settings

Goals:

  • Control all Master pages, Application Master pages and the Alternate CSS url's from code and being able to change these settings at run-time
  • Have only a single copy of the Master page(s) and the alternate stylesheet(s) in your whole farm (ideally on the file system in the _/layouts folder)
  • Apply a custom Master page and stylesheet to Non-Publishing teamsites
  • Apply a different Master page and stylesheet to the application pages (_/layouts pages)

To achieve this I want to use a HttpModule to set the Masterpage and alternate CSS settings at run time. This is probably the only way to change the application.master (do some Googling on it if you don't believe me).

This HttpModule should determine for every request what combination of stylesheet and master should be used.

To update the Masterpage you can easily tell the current page to use another master at runtime:

Page.MasterPageFile = "~/layouts/custom.master";

This works for both regular pages and application pages, although you probably want to use different master pages for the two.

Updating the Alternate CSS is quite a bit harder. This is because the CSS link is rendered by a separate control inside the masterpage:

<SharePoint:CssLink runat="Server"/>

If you dive into the source of this control by using Reflector you'll find a Render() method in which the actual CSS links are written to the screen.

This Render method will write several CSS links from several sources:

1st: It will ask the current SPContext for its CssReferences. This is an internal collection; I didn't find a way to modify this collection

2nd: It writes a link from its own private string m_primaryCssUrl. This is probably the link to core.css. Because it is private you cannot and you do not want to change it. I believe this string is assigned in a obfuscated method called SetDefaults() because it is not assigned anywhere else.

3th:  It writes a link from its own pubic property DefaultURL, finally a public property we can set! Setting this property can look like:

<SharePoint:CssLink runat="Server" DefaultUrl="~/layouts/custom.master"/>

You'll hard-code this property in the Masterpage, meaning that every Masterpage is connected to a specific Stylesheet. If you want to be able to dynamically attach different stylesheets from code (for example based on the user or based on the time of the day, the weather, etc), this is not the way for you.

So you really want to control the Stylesheet on run-time? Fine, but I'll warn you - it's not going to be nice.

First thing, you're not able to access the SharePoint:CssLink  control programmatically to set the DefaultUrl. This is because it has no Id and is not registered in the code-behind. Looping to all controls does not help as well; I can't get a hook to the control...

Luckily the Render() method of the CssLink control also has a 4th source from which it retrieves CSS links;

4th: It writes a link which is defined in one of the current SPWeb properties: m_alternateCssUrl. This property is also accessible from the public property SPWeb.AlternateCssUrl.

So if we set this property it will automatically be rendered by the SharePoint:CssLink control :-)

The downsize to this is that you are actually changing SPWeb properties. If you don't save the SPWeb these changes are discarded after the request, but if the SPWeb is saved somewhere along the page execution path, this setting will be saved as well. Not very nice.  

Custom CssLink Control?

So this SharePoint:CssLink control is not very easy to manipulate at run-time. For the moment I am fine setting the DefaultUrl property in the control itself. This leaves me with a bit less flexibility, but it works and it is actually default functionality. Due to the limited time I have available it's a nice trade-off.  

If you are ready to take more serious matters, there are 2 options I want to consider:

  • 1. Overriding the SharePoint:CssLink control and add our own logic on top of it
  • 2. Creating our own SharePoint:CssLink control
  • 3. Adding the CSS Link directly from the HttpModule.

The code if have so far look like (simplified):

public class MasterPageModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += context_PreRequestHandlerExecute;
    }

    static void context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        Page page = HttpContext.Current.CurrentHandler as Page;
        if (page != null)
        {
            page.PreInit += page_PreInit;
        }
    }

    static void page_PreInit(object sender, EventArgs e)
    {
        Page page = sender as Page;

        if (page.MasterPageFile.ToLower().Contains("application.master"))
        {
            page.MasterPageFile = "~/_layouts/customApplication.master";
        }
        else if (page.MasterPageFile.ToLower().Contains("default.master"))
        {
            page.MasterPageFile = "~/_layouts/custom.master";
        }

    }

    public void Dispose()
    {
    }
}
 
[update] The solution to set the masterpage as shown above does not work for publishing pages. I'm still investigating this issue.

Posted 08-29-2008 4:43 AM by Sander de Koning

Comments

YESChandana -Blog wrote My favorite links from the 4th week of August 2008
on 08-31-2008 8:35 AM

My favorite links from the 4th week of August 2008

Links (9/1/2008) « Steve Pietrek - Everything SharePoint wrote Links (9/1/2008) &laquo; Steve Pietrek - Everything SharePoint
on 09-01-2008 6:03 PM

Pingback from  Links (9/1/2008) &laquo; Steve Pietrek - Everything SharePoint

Örnekleri wrote re: Centralize Master page and Alternate CSS settings
on 11-12-2008 12:36 PM

Cascading Style Sheets (CSS) web design lessons

Css link Properties Attributes - examles

css-lessons.ucoz.com/link-css-examples-1.htm

css-lessons.ucoz.com/link-css-examples-2.htm

Recent Links Tagged With "stylesheet" - JabberTags wrote Recent Links Tagged With "stylesheet" - JabberTags
on 12-30-2008 2:17 PM

Pingback from  Recent Links Tagged With "stylesheet" - JabberTags

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.