Summarize

Sitecore is a complex piece of software by any measure. This series attempts to explore, demystify, and shine a light on some of the complexities involved in deploying Sitecore sites into an existing (and operational) Sitecore instance where source code is contributed by multiple parties.

Configuring your application startup behavior in a Sitecore instance can be a tricky job, with many varied tools and technologies in use to 'set up' your application.

Doing so in a multi-agency environment needs special care and attention because of the nature of bootstrapping it is required that each codebase 'share' that part of the application without causing issues for themselves or other co-hosted sites.

What are the shared areas

Let's start by defining some of the parts that are required to be initialized during application start. There are a wide variety of things that require bootstrapping on the start of the application but some of the more common ones are:

Global.asax

At a high level any code that you would normally keep in the global.asax needs attention, in most instances of a pre-existing implementation it is not possible to make changes to the Global.asax and it is not wise to take a dependance on another agencies libraries or code as these may change without warning. There is one exception to this rule highlighted below.

Dependancy Inversion

Most Sitecore applications nowadays make use of the dependency inversion pattern to decouple components (it's required if you are using MVC). IOC containers need to have their types and rules registered on application start so the container knows how to resolve dependencies. This can be tricky for agencies as you will not have access to the types registered for another vendors site and visa versa. Additionally you need to be sure that in configuring the container for your site, you don't wipe out registrations that have been made for other pre-existing sites.

Glass Mapper

Glass mapper has become an integral tool for complex MVC Sitecore sites to assist in modeling items and template structure as an object graph. This lends itself well to the MVC style of applications and affords much more robust and testable code. The problem is that only one Glass Mapper instance can exist per Sitecore instance, that means it must be configured and centrally managed.

Glass mapper uses its own DI framework independent of that used by the housing application (Castle Windsor), the Castle container needs to be initialized on start up and custom handlers can be registered to perform custom mappings.

Route configuration

The majority of sites are now moving to an MVC architecture which means their route configuration needs to be configured at startup. Because a site can only have a single controller factory it is required that all sites within the same instance not only use the same DI framework they must also share the same container.

There is another danger here that all controllers must be uniquely named across ALL sites regardless of namespace, this means NavigationController

What's the solution

Do no work in Global.asax (or as little as possible)

Make sure that as little as possible work is actually done in the Global.asax. This means moving all your bootstrapping code out to their own classes, or better still an 'infrastructure' library (for maintainability purposes). This means that the default Sitecore Global.asax can be used in situ which also helps when upgrading instances.

WebActivator to the rescue

WebActivator is a great open source project by long time Microsofty David Ebbo.

WebActivator is a NuGet package that allows other packages to easily bring in Startup and Shutdown code into a web application. This gives a much cleaner solution than having to modify global.asax with the startup logic from many packages.

Much more detailed information is available via the Github page but basically WebActivator allows for an assembly directive be placed at the start of a class for that class method to be executed before or after the application start or end events using the PreApplicationStartMethod, PostApplicationStartMethod, PostApplicationStartMethod attributes.

[assembly: PreApplicationStartMethod(typeof(AutofacRegistry), "Start")]
namespace Demo.Infrastructure.Web.Registries
{
    public static class AutofacRegistry
    {
    }
}

But, be careful!

Whilst you can rely on WebActivator executing your method during application start (or end) you cannot be sure of the order other WebActivator directives will execute in. This means you should not be initializing your containers only extending them, that means DI containers, Route registries, GlassMapper registries should all be initialized globally then configured or extended in your 'Activated' classes.

The reason for this is if you are initializing a container or registry and another site has already modified that container then you will overwrite their registrations (and cause problems for that site).

The way around this is to perform all initializations via the Global.asax or a centrally managed library and only enhance containers in the activated components. This is the exception to the 'no work in Global' rule.

Check out the other posts in this series.

Continue reading the next in the series Configuration collisions