application.master and SharePoint Application Page Branding

After the excellent news that SharePoint 2010 lets application pages use the site master page rather than application.master, one may think that all problems are solved. Of course, this is only good news now if you ignore the fact that SharePoint 2010 isn’t here yet, and that even when it gets here, upgrading will take time, and branding efforts need to be redone.

So, what do you do about your current SharePoint 2007 application.master branding? And what about modifying the other application pages, even when SharePoint 2010 ships? I’ll tell you a bit about what I learned from a recent project and how you can make application pages customizations in a supportable manner without the hassle of copying and backing up a ton of [12] files.

The Story So Far

Before that, however, let’s review the common solutions. I’m assuming you are familiar with the problem. If not, it is likely that the remained of this article is completely pointless to you. However, realize that the solution I describe here will be just as applicable to SP2010. The problem will likely remain – there will still be application and system pages you are not allowed to change.

Microsoft Says…

First, there’s the supported methods of copying the LAYOUTS folder, as described in http://support.microsoft.com/kb/944105. The major benefits is that this comes from Microsoft, so if you need help, they can’t really turn you down. The downside, however, are massive, for example the inability to deploy solutions that provision files to the LAYOUTS folder, the manual setup you need in IIS for every web application, and the fact that you need to manually apply any future (although unlikely) updates to the files in the LAYOUTS folder, etc.

To be honest, this solution is bad, except if you’re really desperate about doing things the way Microsoft tells you that you can do things.

HTTP Module

Then there’s the famous HTTP module solution, in which you register an HTTP module that intercepts a page request prior to the master page getting applied to a page. You can read about that solution here: http://vspug.com/dwise/2007/01/08/one-master-to-rule-them-all-two-actually/

The good news is that this is probably not voiding your warranty, and you get to set exactly the master page you want, including possibly your site master page. The bad news is that you’re still left with the need for manual updates for any patches and the fact that things can simply break. Besides, you still need IIS work, at least web.config modification, and you need to pay attention to any other HTTP modules running, for example in a publishing site.

I’ve seen this solution recommended by some Microsoft Consulting people, but frankly, I still don’t like it.

CSS branding

Regardless of which solution you choose, for simple layout and bells- and whistle stuff, you may get away with a skilled CSS person and a good theme. Sadly, the CSS options in SharePoint are rather limited out-of-the-box, and you need to jump some hoops to get custom themes for any SharePoint solution. I’ve described one such method in issue 6 of USPJ for a solution called SPThemes. SPThemes allows you to inject CSS after core.css and even change CSS on a user-by-user basis.

The bad news in any case is that CSS is extremely limited by nature; you cannot easily change the structure of a page using CSS alone, nor can you add new content or controls like you can with a completely custom application.master.

The One Solution to Bind Them All (Almost)

None of the solutions described so far are actually SharePoint solutions. They rely on mucking about with IIS, modifying the [12] files, or using client-side browser functionality. Surely, SharePoint, being such an incredibly powerful tool must be able to solve this issue?

Before I describe the solution, I want to describe the scenario in which this came up. Well, one of the scenarios; I’m sure this situation has been the bane of many a SharePoint branding project in the past.

In our case, however, the customer is a multi-national company with tens of thousands of employees around the globe from about as many cultures as there are on our small sphere in the universe.

One policy requirement is that no solution used in this company can use icons. The reason? Well, what may be a perfectly logical icon to you and me may be a nasty gross insult to someone in a different culture, and vice versa. Oh, and another requirement is that custom JavaScript must be avoided unless it’s out-of-the-box functionality. And you need to support IE6.

Did I mention that we need this to work on any out-of-the-box sites while supporting all default functionality such as adding the tree view navigation option?

This, of course, means that you need to hide any and all icons, and using a bit of Display: none; magic in CSS, you can get most of the icons to disappear. But what happens if you turn on the tree view navigation in an out-of-the-box team site? You get an SPTreeView control that shows the site, list and, library icons whether you like it or not.

In your normal master page, you can simply modify or replace the SPTreeView of a default master page with a regular ASP.NET TreeView control, and viola, Bob’s your uncle and has taken your icons away. And you’d think that, since application.master doesn’t even include the SPTreeView control, that you’d be home safe.

Sadly, some of the application pages in LAYOUTS, such as people.aspx, add the SPTreeView control to the PlaceHolderLeftNavBar content placeholder, and you’re back to square one, risking insulting someone because the red person in the SharePoint site icon is to the right and not the left. Or something.

Ah, but CSS can solve that. Except (and I’m trusting the designer who told me this) it’s not easy to set CSS styles for icons in an SPTreeView while maintaining the need to support IE6. Apparently, and I’m very much not a CSS guy, you can’t select elements based on attributes in IE6 or something like that.

One option is to use jQuery, which probably works very nice, except we can’t use custom JavaScript. So, you’re back to modifying [12] files, which is a horrible solution, even if you to the IIS _layouts redirect that Microsoft suggests.

What we need is to replace the SPTreeView control with an ASP.NET TreeView control without touching a page that forcibly adds the SPTreeView control.

And, just for the heck and beauty of it, I want to use SharePoint only techniques and not damage a single Microsoft-provided file. It wasn’t a requirement, but I do like the occasional challenge, of nothing else than to remind myself how incredibly cool SharePoint can be.

Sounds impossible? Not for SharePoint. This is a case for…

DelegateControls!

Yeah, OK, I’m not going to kid you here, this involves some .NET code. And, I’ll admit, some rather not-too-pretty .NET code, but look at the principles and not necessarily these examples.

A DelegateControl, as you likely know, works by allowing plug-in functionality to pages. You can write the plug-in in .NET so you can pretty much run whatever you like. The really cool thing is that both regular master pages and application.master has a DelegateControl called AdditionalPageHead.

Note: The default publishing master pages does not include AdditionalPageHead. You may con
sider adding this to your custom publishing master page if you want to use this method.

The plug-in you write will also have access to the regular ASP.NET control tree of the page in which it runs. This is one of those things I truly love about SharePoint; it’s ASP.NET in its essence so what works in ASP.NET usually works in SharePoint as well.

In our case, we needed to replace the SPTreeView of any page, not just application pages, but all other pages as well. The code we ended up running is in essence this:

Control SPTreeViewControl = Page.Master.FindControl(“ctl00$PlaceHolderLeftNavBar$WebTreeView”);

if (SPTreeViewControl != null)
{
    try
    {
        SPTreeView orgTreeView = (SPTreeView)SPTreeViewControl;

        TreeView newTreeView = new TreeView();
        newTreeView.CssClass = orgTreeView.CssClass;
        newTreeView.ExpandDepth = orgTreeView.ExpandDepth;
        newTreeView.DataSourceID = orgTreeView.DataSourceID;
        newTreeView.ShowExpandCollapse = orgTreeView.ShowExpandCollapse;
        newTreeView.NodeIndent = orgTreeView.NodeIndent;

        TreeNodeBinding tnBinding = new TreeNodeBinding();
        tnBinding.NavigateUrlField = “NavigateUrl”;
        tnBinding.TextField = “Name”;
        newTreeView.DataBindings.Add(tnBinding);

        // TODO: Add other properties if needed.

        SPTreeViewControl.Parent.Controls.Add(newTreeView);
        SPTreeViewControl.Parent.Controls.Remove(SPTreeViewControl);

    }
    catch { }
}

Yes, I said it would be ugly, but if you look at the principles, namely using DelegateControl controls to manipulate the control tree of the page, you may perhaps see the benefit of this approach.

Here is the result, applied to a lab machine I have, all at the flick of a switch and without even touching any [12] files:

Figure 1

Of course, these aren’t application page menus, so take a look at this shot, taken from the User and Groups (people.aspx) page of the same site. I’ve removed the quick launch menu to save some space:

Figure 2

DelegateControl plug-ins are added as features so they can be activated an deactivated with the click of a button. Another cool thing is that DelegateControl features can have any scope, meaning you can apply your feature either at a web level or at any level up to the entire farm. Since you’re running code, you can even change the behavior based on any number of parameters, such as showing the default layout to site administrators while showing a modified layout to all other users.

Oh, and if it’s not clear by now; this is a completely supportable method for manipulating application pages. Put this code in a WSP solution, deploy, and never touch a single out-of-the-box file.

This Sounds Magical – Where’s the Catch?

I did say that this solution is ‘almost’ the one solution to bind them all.

Using this method, you can, in theory, rebuild, replace, modify, or add any control to the page or master page of the current request. In theory, you can rebuild the control tree to output valid HTML without tables and without breaking supportability.

Doing design in a .NET code way is extremely time consuming. This method works best for minor changes, such as replacing or modifying controls, adding a few DIV elements here and there or perhaps changing a piece of text. Since a lot of content is not .NET controls directly, and examples of this is the table based layouts, you end up with modifying literal text for more serious design changes.

In theory, this methods works for anything. In practice, don’t plan on completely rebuilding all the application pages.

.b

Found this article valuable? Want to show your appreciation? Here are some options:

a) Click on the banners anywhere on the site to visit my blog's sponsors. They are all hand-picked and are selected based on providing great products and services to the SharePoint community.

b) Donate Bitcoins! I love Bitcoins, and you can donate if you'd like by clicking the button below.

c) Spread the word! Below, you should find links to sharing this article on your favorite social media sites. I'm an attention junkie, so sharing is caring in my book!

Pin It

Published by

Bjørn Furuknap

I previously did SharePoint. These days, I try new things to see where I can find the passion. If you have great ideas, cool projects, or is in general an awesome person, get in touch and we might find out together.

6 thoughts on “application.master and SharePoint Application Page Branding”

  1. atesfay1,

    Well, yes, but the former method, meaning essentially you take a backup of your LAYOUTS files and then edit away, is practically the same as saying "just edit but make sure you can discard all your changes at a moments notice". Since your original files can be restored from any similar setup, also essentially meaning any default SharePoint setup, you don't really need to back up first; it's just more convenient.

    Not just that, but using method 1 you also need to manually update the backup LAYOUTS files every time before updating SharePoint, or you need to temporarily revert your changes prior to running any update. Otherwise the update wont be able to affect the original files or you risk the update overwriting your own files.

    The issue here, really, is that editing these files is a bad idea.

    .b

  2. Hi,
    (scenario: variation sites.
    default functionality: master page is at the site collection level, refers to css from the same location)
    when it comes to application pages, in a variation site(subsite) the style breaks, but if you look at the other site pages they work fine.

    our application pages show a top navigation, its the custom one.. and on visiting application pages, such as “_layouts/settings.aspx” the view breaks completely.

    Please help.

Leave a Reply

Your email address will not be published.