Friday, November 25, 2011

AlternateCSSUrl + Save site to template = AlternateHeader issue

Last week I was experiencing broken foundation pages or malformed top navigation bars. In my case this was related to having a custom (aka Saved) site template and the AlternateCSSUrl setting.

The AlternateCSSUrl setting

Most companies have a specific corporate identity and as a SharePoint designer they ask you to change the look and feel of the teamsites to adhere to that identity. In some cases people use themes to implement the color scheme and main font family. Something which is very useful as it also creates the gradients for you. In other cases this might not be enough and additional CSS is required to change for instance the position, background images, line spacing etcetera.

There are various ways to attach your custom CSS to the page. Some people are activating the Publishing Infrastructure and Publishing features. This results in a Masterpage link on the Site settings page. On that page you are able to enter an Alternate CSS link. That link will be automatically added to every page by the CSS link control which is part of the default master page. It will be added after your (themed) Core css files.

But what if you are not using the publishing features? In those cases I would definitely not recommend editing the master page. There are two options:

- Build a FeatureActivated event receiver which will set the AlternateCSSUrl property and apply the theme. Do not forget to implement the FeatureDeactivating feature as well.

- Build a custom action which is a scriptlink and add a scriptblock which will include the CSS in the header using javascript for instance.

Personally I like the first option most and use the second one for including for instance CSS that is required by JQueryUI. The disadvantage of the second one is that it will be injected, which might be noticeable.

If you are implementing the first method then you will need an event receiver. The Event Receiver would look like:

image

Save Site as template
Assume that you have created a new site using an out of the box Teamsite template and the solution that applies a new theme and sets an alternateCSSUrl using a feature event receiver and feature stapling. Everything looks fine and you start configuring your site. At some point you would like to save the current site as a template in order to create subsites using that template.

You browse to site settings and select the option Save Site to template. This link will be hidden as soon as you are using the publishing features and it is not recommended to save templates of publishing sites.

The saved template will be stored in the Solutions gallery of the site.

Now create a subsite using the newly saved site template. Browse to Site Actions -> New site -> select your custom site template, enter a subsite name, URL name and press OK. The subsite will be created and once that process finishes you will be redirected to the homepage of the newly created subsite.

The issue
If you have followed the steps as described above you have a newly created subsite. Try to browse to the Site settings page. You may experience one of the following symptoms:

- the header shows but nothing beneath the top navigation

- you see a site settings page but there CSS code is displayed in the top navigation bar

- you encounter an unexpected error (most likely)

What has happened?
If you try to render for instance the Site Settings page, the page will try to render the top navigation. As the Site Settings page is a foundation page, the top navigation is different than other pages from the _layouts directory which are related to the publishing features like Masterpage or Welcome page links.

The Settings.aspx page uses the v4.master unless you have specified otherwise.

The v4.master page defines a contentplaceholder for the top navigation. Inside the placeholder you will see a ASP:Menu control for rendering the top navigation. However, the contents of the placeholder control will be overridden by the settings.aspx page.
In the settings.aspx page you will see that instead of the ASP:Menu control an user control will be used called LinkSection.ascx. This control you can find in the ControlTemplates folder on each SharePoint server.

The LinkSection control checks a web property called AlternateHeader. According to MSDN the AlternateHeader can be used to define an ASPX page to render an alternative top navigation.

When we check the AlternateHeader property of our newly, malformed subsite, we will notice that it has been provisioned with our AlternateCSSUrl value!

Well, that is certainly NOT what we want and it seems to be a bug.

The solution
Try to set the AlternateHeader back to the null value using PowerShell and you will discover that the subsite works perfectly, including the custom CSS and theme like on the root site:

$w = Get-SPWeb -Identity http://urltoyour/subsite
$w.AlternateHeader = $null


Note:
It seems that the issue has been solved by a hotfix but as most companies only apply Service Packs and no CU’s unless business critical, I would definitely recommend to clear the AlternateHeader yourself.