Custom Sitecore Pipelines

Pipelines are a very useful feature in Sitecore, one that I make use of a great deal.  I see a great many Sitecore website solutions that create their own processors to add to the existing pipelines (or which override existing pipeline processors), but I very rarely see solutions that have created their own pipelines. Usually I only see it in modules.  I think that developers might be missing a trick, as there are a great many things that you can do with a simple pipeline and it provides easy extensibility throughout the project lifetime.

Pipelines, to my mind, should be used to solve a problem where you have (or will have) discrete pieces of logic that may be added to at any time.  Often but not always, these operations occur in a particular order.  There will usually also be one or more results of the pipeline that all of the operations will contribute toward in some way.  A few examples of such problems are:

  1. Canonical URL generation
    This is one of those things that you will continuously be extending on some sites.  Typically, the canonical URL will be the URL of whatever the current page item is.  However, on some parts of your application you may want to include certain query strings.  You may add another set of pages that requires slightly different logic.  By using a pipeline, you can keep neatly extending your logic without creating a Frankenstein class.
  2. Complex analytics tag generation
    This is possibly my favourite application of pipelines.  Sometimes all you do for analytics on a website is drop the same snippet of HTML/JS onto every page on the site; but sometimes (like with Omniture, ComScore, WebTrends, and many others) you need to set a slew of properties, whose values or presence will vary depending on the page you are on, and what the user is doing.  By using a pipeline, you are ensuring that you can easily add to your logic at any point in the future.
  3. Query building
    You may have a search page using ContentSearch or some other technology that has a lot of different switches, which alter the predicates in your query, or which change other query parameters like page size and sorting. Put all the discrete bits of logic into individual processors and let the pipeline do the work. You may have to put a bit more thought into your arguments class, but you’ll be able to test your processors and add to them easily.

Creating a custom pipeline is really straight-forward: pick a name, and pick your arguments. For naming, I can’t provide too much insight; aside from the suggestion that you make sure your pipeline names won’t conflict with others (I usually add a prefix to my pipelines, although I recently found out about a feature called pipeline groups that I might investigate and post about another time). For arguments you can either use the basic ProcessorArgs class, which provides no result; or create a custom class that inherits from PipelineArgs – most often, I find that I do the latter.

The only real requirement for a pipeline processor is that it must have a public Process(PipelineArgs) instance method (the argument type may also inherit from PipelineArgs as shown later).  Personally, I prefer to create an abstract, generic base class like the one below that all my processors will use but it is completely optional:

using System;
using Sitecore.Pipelines;

namespace Sample.Web.Application.Pipelines
{
    public abstract class PipelineProcessor<TPipelineArgs> where TPipelineArgs : PipelineArgs
    {
        public abstract void Process(TPipelineArgs args);
    }
}

I then create folders to represent each of my pipelines, and to produce a namespace structure much like the one applied in Sitecore.Kernel.  This folder contains all the processors for that pipeline, and the custom PipelineArgs class if that pipeline has one. A pipeline processor using a custom arguments class (MyPipelineArgs) may look as follows:

namespace Sample.Web.Application.Pipelines.MyPipeline
{
    public class Processor1 : PipelineProcessor<MyPipelineArgs>
    {
        public override void Process(MyPipelineArgs args)
        {
            // Do something
        }
    }
}

Next, you have to add your pipeline and processors to the Sitecore configuration. You should do this using an include file (I’ve blogged about this previously), a little like the following sample:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
    <pipelines>
      <myPipeline>
        <processor type="Sample.Web.Application.Pipelines.MyPipeline.Processor1, Sample.Web.Application" />
        <processor type="Sample.Web.Application.Pipelines.MyPipeline.Processor2, Sample.Web.Application" />
        <processor type="Sample.Web.Application.Pipelines.MyPipeline.Processor3, Sample.Web.Application" />
      </myPipeline>
  </sitecore>
</configuration>

The last thing, of course, is how to invoke your pipelines.  It’s really simple:

var args = new MyPipelineArgs();
CorePipeline.Run("myPipeline", args);

This method will invoke all the processors, in order, and synchronously.  You would obviously substitute any custom arguments class and the pipeline name for yours, fetching the result, if you have one, from your custom args instance.

So that’s it, hopefully you find a way to apply pipelines to some benefit in your own solutions if you don’t already.