In a previous post, I extolled the virtues of deploying our branding code in a solution. While I still make that recommendation without any reservations, it's important to note that you may need TWO solutions to deploy your branding customizations.

History 

First, let's do a quick review of some of the generic components I used in branding our MOSS environment (using the HTTP module approach for LAYOUTS customizations):

  • Customizations to the GAC 
    • Feature Receiver DLL for the branding features
    • Some custom web part assemblies
    • Redirect Module DLL
  • Customizations to the "12" directory:
    • Custom application.master (applied via a redirect)
    • Custom simple.master (applied via a redirect)
    • Custom images
    • Custom Theme
    • A branding feature for Meeting Workspaces
    • A branding feature for all the other site templates
    • Branding feature stapler 
  • Customizations to web.config:
    • SafeControls entries for the custom web parts
    • Redirect module configuration info

Everything except the redirect module configuration info (which we configured manually) is easily accomodated by the Solution framework, so that's exactly what I put in the original SINGLE branding solution file. So deploy all that stuff to your Web Front End servers, and you're good to go, right? Not entirely...

The Problem...

Two odd symptoms occurred in our regression testing. When we created sites/site collections from self-service site creation, STSADM on the WFE servers, or from the Create Page in a site, branding was applied. This is good. :) However, when we created site collections via STSADM from an app server or from Central Administration > Application Management > Create Site Collection, the branding was missing. This is bad. :)

Why? The Central Admin server - and all non-WFE servers - were missing the branding code. The feature stapler and everything referenced by it - the branding features, the feature receiver (since the features referenced it), and the custom theme (since the feature receiver attempted to set a new site's theme to the custom theme) - need to be on these servers in order for the site creation to complete with all branding applied.

The Solution...

In case you didn't know already (I didn't, which was the cause of this issue), there are two types of Solution deployments - Web Front End (which only pushes the changes to servers hosting the web application role) and Application Server (which pushes changes to ALL SharePoint servers in the farm). I don't remember the complete solution manifest spec, but one other restriction that's relevant to this scenario is that only the Web Front End deployment type supports creation of SafeControl entries.

Since I had a set of code that needed to be on ALL the servers as well as a couple of SafeControl entries, the simplest thing to do was to divide the customizations into two separate solutions - "core" branding and "web server" branding. The core solution holds all the components that are required on all servers, while the web server contains only the components that are needed to render the branded sites (like images, web parts, and LAYOUTS customizations).

Here's the breakdown:

"Core" Branding Solution

  • Customizations to the GAC
    • Feature Receiver DLL for the branding features
    • Redirect Module DLL
  • Customizations to the "12" directory:
    • Custom Theme
    • A branding feature for Meeting Workspaces
    • A branding feature for all the other site templates
    • Branding feature stapler 

    "Web Server" Branding Solution

  • Customizations to the GAC 
    • Some custom web part assemblies
  • Customizations to the "12" directory:
    • Custom application.master (applied via a redirect)
    • Custom simple.master (applied via a redirect)
    • Custom images
  • Customizations to web.config:
    • SafeControls entries for the custom web parts

    For ease of maintenance, I still used WSPBuilder for creating the manifests and .WSP files - this just required a minor tweak to the build script, which now looks something like this:

    REM build core server customizations
    wspbuilder.exe -solutionid 12345678-1234-1234-1234-1234567890ab -deploymentservertype ApplicationServer -wspname core-branding.wsp -excludefiles "a_list_of_all_the_wfe_files.txt" 

    REM build web server customizations
    wspbuilder.exe -solutionid 12345678-1234-1234-1234-1234567890ac -deploymentservertype WebFrontEnd -wspname webserver-branding.wsp -excludefiles "a_list_of_all_the_core_files.txt"

    Enjoy...