Creating and running custom pipelines in Sitecore

15

August 27, 2008 by Alistair Deneys

A lot of what happens when you request a page in Sitecore is handled by pipelines. Actually, Sitecore makes extensive use of pipelines all the way from handling page requests, to uploading files and saving items through the UI.

So what is a pipeline? A pipeline is a discrete set of steps, executed in order. It is an architectural design you can employ for certain cases in your applications. If I have a series of tasks which need to be performed to accomplish a task, then a pipeline may be the way to go. A pipeline will execute the steps in order, so I could use a pipeline for my ordered tasks as well as my unordered tasks (as the order doesn’t matter we don’t care that it was executed in order).

So what can we use this for in the real world? Let’s take validation as an example. Let’s say we have a purchase order item. Before it can move through to the “ship it!” step in the workflow the order must pass validation. That validation usually contains many discrete steps such as billable amount is greater than 0, date is in the past, GST or other taxes have been calculated properly, etc. Each of these discrete steps can be handled in isolation by a separate method or class.

Sitecore uses a pipeline to generate and populate the Sitecore.Context class. This class contains information about the current user, the current site, the current item being requested, etc. Each step in the httpRequestBegin pipeline populates just a single item in the context. The Sitecore pipelines also allow passing of an object through each step. This object can be manipulated by any of the steps and passed through to the next step until the end is reached and the object can be used by whatever executed the pipeline in the first place.

I get many benefits from using a pipeline architecture, the most relevant of which are:

  • Testability: Each step in the pipeline is usually very small and performs only a single task. This makes it much easier to test each smaller piece and pinpoint bugs rather than testing a big composite piece which might perform many steps in a single method and require more debugging to work through the bugs.
  • Recomposition: Pipelines are generally configurable. The pipeline architecture employed by Sitecore allows us to define the pipeline in web.config. The pipeline definition includes what each step is, and the order of those steps. We could also reuse those steps in another pipeline.

So let’s create our own custom pipeline using the Sitecore pipeline architecture. This example pipeline is going to check that an item is valid and passes a set of validation rules implemented in code. (This is just a demo. Please refer to Alexey Rusakov’s awesome validation rules blog posts for how to properly do validation in Sitecore 6). All pipelines in Sitecore require the method being invoked to accept a subclass of Sitecore.Pipelines.PipelineArgs. So we will start by defining our own subclass of the PipelineArgs class that will hold relevant information for our pipeline and allow passing of that data from step to step.

using Sitecore.Data.Items;
using Sitecore.Pipelines;

namespace CustomPipeline
{
  public class CustomPipelineArgs : PipelineArgs
  {
    private bool m_valid = false;
    private string m_message = string.Empty;
    private Item m_item = null;

    public bool Valid
    {
      get { return m_valid; }
      set { m_valid = value; }
    }

    public string Message
    {
      get { return m_message; }
      set { m_message = value; }
    }

    public Item Item
    {
      get { return m_item; }
      set { m_item = value; }
    }

    public CustomPipelineArgs(Item item)
    {
      m_item = item;
    }
  }
}

Each step in the pipeline is called a “processor”. We need to make sure that each processor can accept the args we defined above. The easiest way to do this is to either use an base class or an interface. I’ll go with an interface here because a base class would not be providing any functionality.

namespace CustomPipeline
{
  interface ICustomPipelineProcessor
  {
    void Process(CustomPipelineArgs args);
  }
}

This interface locks each processor into defining the “Process” method which will be called from the pipeline. Next we define each processor class and fill in the Process method to perform it’s specific function. In this example I’ll provide 2 processors.

namespace CustomPipeline
{
  public class DateSet : ICustomPipelineProcessor
  {
    public void Process(CustomPipelineArgs args)
    {
      if (args.Item["date"] == string.Empty)
      {
        args.Valid = false;
        args.Message = "Date has not been set";
      }
    }
  }

  public class TextSet : ICustomPipelineProcessor
  {
    public void Process(CustomPipelineArgs args)
    {
      if (args.Item["text"] == string.Empty)
      {
        args.Valid = false;
        args.Message = "Text has not been set";
      }
    }
  }
}

The DateSet class checks to make sure the date field of the item is not empty and the TextSet class checks to make sure the text field isn’t empty.

Now that we have all the pieces of our pipeline defined we need to create the pipeline in web.config. Open up web.config and find the “pipelines” element. Add a new element before the closing tag containing the XML below.

<CustomPipeline>
  <processor type="CustomPipeline.DateSet, CustomPipeline" />
  <processor type="CustomPipeline.TextSet, CustomPipeline"/>
</CustomPipeline>

We don’t need to define the Process method in the above processor elements as that is the name of the default method the pipeline processor will try to call. We can of course override that method by providing the method to call in the processor tag.

Now all we have to do is invoke the pipeline from somewhere in our code to run the validation over a given item. We need to create the CustomPipelineArgs object, populate it, then call into Sitecore to run our pipeline and pass in the arguments.

CustomPipelineArgs pipelineArgs = new CustomPipelineArgs(item);
CorePipeline.Run("CustomPipeline", pipelineArgs);
if (!pipelineArgs.Valid && !string.IsNullOrEmpty(pipelineArgs.Message))
{
  // Execute code here to deal with failed validation
}

So with just a few lines of code and configuration we can start to reap the benefits of a pipeline architecture for performing our applications processes, leveraging the Sitecore pipeline processor.

About these ads

15 thoughts on “Creating and running custom pipelines in Sitecore

  1. Much needed post. Maybe you could tackle UI (Client) pipelines next? :-)

  2. Mark Cassidy says:

    Excellent stuff this, thanks :D

    Just a thought; Aren’t pipeline processors supposed to check the .Aborted flag, or is this all part of what the CoreProcessor handles?

    Or maybe asked differently – if the first step in the pipeline flags abort, will the remaining steps execute?

  3. adeneys says:

    Thanks Alexey, I’ll put the UI pipelines on the list :)

  4. adeneys says:

    Hi Mark,
    Yeah, the CorePipeline will check the aborted flag, which can be set by calling the AbortPipeline method on the PipelineArgs. If in the first step I called AbortPipeline, then the remaining steps wouldn’t be run. And really, this example probably wasn’t the best. I just wanted to show how easy it was to create and run custom pipelines. Thanks for the comments!

  5. [...] more about pipelines at Coffee=>Coder=>Code or at the Getting To Know Sitecore with Adam Conn or at the John West Sitecore [...]

  6. [...] more about pipelines at Coffee=>Coder=>Code or at the Getting To Know Sitecore with Adam Conn or at the John West Sitecore [...]

  7. Mark says:

    Why even bother with your interface? Sitecore should really have its own interface for which each process should implement. If every processor needs to have a Process() method then Sitecore should expose an interface for that and require developers to implement it. I don’t understand why you took the step to make your own interface, it’s not a contract you need to abide by from Sitecore.

    • Alistair Deneys says:

      Hi Mark,
      It was more for me and my common dev practices, to make sure my processors all had the Process method and accepted the correct type of arguments.

  8. Aby says:

    Thank you so much for sharing the knowledge.

  9. [...] to use a custom Sitecore pipeline for my SmartTreeList type. Here’s a great synopsis of how to create a custom pipeline. This allows me to apply different logic for determining the “Start Folder” depending [...]

  10. Vinayak says:

    nice article … .thanks for sharing….

  11. [...] Creating and Running custom pipelines (by Alistair Deneys) [...]

  12. […] the Sitecore Digital Marketing System. For information about creating and invoking pipelines, see Creating and running custom pipelines in Sitecore by Alistair […]

  13. vikas Rathore says:

    nice article..Thanks

  14. […] the Sitecore Digital Marketing System. For information about creating and invoking pipelines, see Creating and running custom pipelines in Sitecore by Alistair […]

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

The views expressed on this blog are solely my own and do not necessarily reflect the views of my employer.
Follow

Get every new post delivered to your Inbox.

Join 44 other followers

%d bloggers like this: