Creating Site Specific Pipelines for Multi-Site Implementation in Sitecore

tl;dr Use the Sitecore Configuration Factory to pass parameters to enable Pipelines to only run for specific sites

I’ve been working on a few multi-site Sitecore implementations lately and the majority of the time most brands within the same company umbrella all want similar functionality, which is very nice and easy for us developers. But as you start to work on larger implementations with different brands it will be inevitable that they all have slightly different requirements.

Pipelines provide us a great way to customize Sitecore, but they run for all requests unless we put in some hacky code:

public override void Process(HttpRequestArgs args)
{
    if (!Sitecore.Context.Site.Name.Equals("mysite1") || !Sitecore.Context.Site.Name.Equals("mysite2"))
        return;

    // run your site specific code
}

Instead we can use the Sitecore Configuration Factory to let us specify the sites the Processor should run for in config:

<pipelines>
  <httpRequestBegin>
    <processor patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" 
               type="SitecoreSandox.Pipeline.SiteSpecificPipelineProcessor, SitecoreSandox">
      <sites hint="list">
        <site>site1</site>
        <site>site2</site>
      </sites>
    </processor>
  </httpRequestBegin>
</pipelines>

The attribute `hints=”list”` specifies that a list of parameters is being passed to your class.

public abstract class SiteSpecificPipelineProcessor : HttpRequestProcessor
{
    public List<string> Sites { get; set; }

    protected SiteSpecificPipelineProcessor()
    {
        Sites = new List<string>();
    }

    public override void Process(HttpRequestArgs args)
    {
        if (!Sites.Contains(Sitecore.Context.Site.Name))
            return;

        Run(args);
    }

    protected abstract void Run(HttpRequestArgs args);
}

Define a property that matches your parameter, it is not case sensitive. It is important to initialize list types in your constructor though, for simple types you do not have to do this.

Now we can simply check if the Context Site is one which this pipeline should run for otherwise we can simply ignore it. Inherit the above abstract class and implement your logic in the `Run()` method.

There are also some great posts on the Sitecore Configuration Factory by fellow MVP Mike Reynolds.

Configuration in multi-project scenario

It is often the case that when dealing with more complex solutions you will separate the code into separate projects: a shared core project and separate projects for each site which then get merged when deployed. In such situations you would want to separate the configuration for each site.

Define your processor in your core project, which essentially provides a skeleton definition. Currently with the below code this will not run for any sites.

CoreSites.config

<pipelines>
  <httpRequestBegin>
    <processor patch:before="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" 
                type="SitecoreSandox.Pipeline.SiteSpecificPipelineProcessor, ML.SC.Business" hint="MyProcessor">
      <sites hint="list">
      </sites>
    </processor>
  </httpRequestBegin>
</pipelines>

Then for each specific site we can patch in that this processor should run:

SiteSpecific.config

<pipelines>
  <httpRequestBegin>
    <processor hint="MyProcessor">
      <sites>
        <site name="site1">site1</site>
      </sites>
    </processor>
  </httpRequestBegin>
</pipelines>

Note the `hint=”MyProcessor”` attribute. This makes it easy for us to provide a patch config in our site specific project without having to specify the (long) type attribute. It also means if we decide to change the type we only need to do it in one place.

The `name` attribute has also been specified in the `site` element. Without this patching multiple times means only the last applied config is added. This adds a unique attribute to the element which means they are added rather than replaced. The attribute itself is ignored and not used anywhere.

Advertisements

5 comments

  1. Sen Gupta · August 30, 2014

    Great approach!

  2. jammykam · December 22, 2014

    Looks like a few of us blogged about the same thing around the same time, I’ve just come across this article from SitecoreJohn: http://www.sitecore.net/Learn/Blogs/Technical-Blogs/John-West-Sitecore-Blog/Posts/2013/09/Site-Specific-Pipeline-Processors-in-the-Sitecore-ASPNET-CMS.aspx

  3. Pingback: Helix: Patching your Config Patches for Specific Environments | jammykam

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s