Skip to main content

Sitecore

Patching Sitecore Processors Tips and Tricks

Pipeline@1x.jpg

One of the questions I hear from Sitecore developers that have just created a processor is, how do I position my processor to execute before or after an existing processor in a pipeline?    If you place the processor in the wrong spot then the processor that runs before your processor could have aborted the pipeline before your code had a chance to do anything.  The processor could have also changed the Pipeline Argument values to something your code needs in order to execute correctly.

This is about patching a processor in a pipeline but this same logic could also apply to patching other things in Sitecore such as Handlers, Sites, Strategies, etc.    Please be aware that this will help with inserting the processor into a pipeline in a certain order but your processor could still not be in the order you want if another config file is read after yours by Sitecore.

How does Sitecore patch a Processor

In order to understand how to patch processors, we first need to understand what Sitecore is doing behind the scenes.   Let’s look at a couple of methods under the Sitecore.Update.dll.

  • Sitecore.Update.Xml.Patch.ConfigFilePatchHelper.IsPatchingAttributeName
    • Sitecore is checking that the “patch:” attribute exists for your processor to determine if you want to place the processor in a certain place.    Notice in the example given the patch keyword occurs before deciding how you want to insert the processor in the pipeline.
      • Example: <processor type=”Sitecore.Cintel.Endpoint.Plumbing.InitializeRoutes, Sitecore.Cintel” patch:after=”*[last()]” />
  • Sitecore.Update.Xml.Patch.ConfigFilePatchHelper.DetermineInsertOperation
    • Sitecore is looking for 3 different keywords (6 if you include the aliases) to determine where to insert the processor
      • ‘after’ or ‘a’
        • Example: <processor patch:after=”*[last()]” type=”Sitecore.Cintel.Endpoint.Plumbing.InitializeRoutes, Sitecore.Cintel”  />
      • ‘before’ or ‘b’
        • Example: <processor patch:before=”*[1]” type=”My.Custom.Pipelines.GlobalSettings.CustomContext, My.Custom” />
      • ‘instead’ or ‘i’
        • Example: <processor patch:instead=”processor[@type=’Sitecore.Pipelines.ExecutePageEditorAction.InsertRendering’]” type=”My.Custom.Pipelines.ExecutePageEditorAction.InsertRendering, My.Custom” >

All of the stuff inside of “patch:before”, “patch:after”, or “patch:instead” such as “*[last()]” is using XPATH to do the rest of the work.   I recommend looking over this page if you want more ways to use XPATH.

Insert Operations Examples

I’m going to use the <renderField> pipeline below as an example of how to insert a custom processor in multiple ways since it has so many processors.   I did modify it a little bit so that I could give more examples.

<renderField>
    <processor type="Sitecore.Pipelines.RenderField.SetParameters, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetTextFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.ExpandLinks, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetImageFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Buckets.Pipelines.RenderField.GetLinkFieldValue, Sitecore.Buckets" patch:source="Sitecore.Buckets.config"/>
    <processor type="Sitecore.Pipelines.RenderField.GetInternalLinkFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel" method="Execute" />
    <processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetDocxFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetIntegerFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.GetNumberFieldValue, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel"/>
    <processor type="Sitecore.ContentTesting.Pipelines.RenderField.HighlightContentChange, Sitecore.ContentTesting" patch:source="Sitecore.ContentTesting.config"/>
    <processor type="Sitecore.Pipelines.RenderField.ProtectedImageLinkRenderer, Sitecore.Kernel" patch:source="Sitecore.Media.RequestProtection.config"/>
    <processor type="Sitecore.Pipelines.RenderField.RenderWebEditing, Sitecore.Kernel"/>
    <processor type="Sitecore.Pipelines.RenderField.SetAnchorsPositionInLinks, Sitecore.Kernel"/>
</renderField>

Example below will be used to show how to insert a processor into the <renderField> pipeline

<processor type="My.Custom.Pipelines.RenderField.GetCustomFieldValue, My.Custom"/>

Examples

Insert the processor to run before all of the other processors in <renderField> have executed

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
      <renderField>
         <processor patch:before="*[1]" type="My.Custom.Pipelines.RenderField.GetCustomFieldValue, My.Custom" />
      </renderField>
   </sitecore>
</configuration>

Insert the processor to run after all of the other processors in <renderField> have executed

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
      <renderField>
         <processor patch:after="*[last()]" type="My.Custom.Pipelines.RenderField.GetCustomFieldValue, My.Custom" />
      </renderField>
   </sitecore>
</configuration>

Insert the processor to run after the first 2 processors in <renderField> have executed

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
      <renderField>
         <processor patch:after="processor[position()=3]" type="My.Custom.Pipelines.RenderField.GetCustomFieldValue, My.Custom" />
      </renderField>
   </sitecore>
</configuration>

Insert the processor to run after the GetImageFieldValue method in <renderField> has executed

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
      <renderField>
         <processor patch:after="processor[@type='Sitecore.Pipelines.RenderField.GetImageFieldValue, Sitecore.Kernel']" type="My.Custom.Pipelines.RenderField.GetCustomFieldValue, My.Custom" />
      </renderField>
   </sitecore>
</configuration>

Replace the GetMemoFieldValue processor with our custom processor in <renderField>

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
      <renderField>
         <processor patch:instead="*[@method='Execute' and @type='Sitecore.Pipelines.RenderField.GetMemoFieldValue, Sitecore.Kernel']" type="My.Custom.Pipelines.RenderField.GetCustomFieldValue, My.Custom" />
      </renderField>
   </sitecore>
</configuration>

The interesting thing about the <renderField> pipeline is that it has 2 processors that use the method GetLinkFieldValue (Sitecore and Buckets) but lets say we create a third one and we want it to be the second one in the list then we could do something like this below

<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
   <sitecore>
      <renderField>
         <processor patch:after="processor[contains(@type, 'GetLinkFieldValue')][position()=2]" type="My.Custom.Pipelines.Rendering.GetLinkFieldValue, My.Custom" />
      </renderField>
   </sitecore>
</configuration>

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

CJ Morgan

CJ became a certified Sitecore developer in 2015. In his spare time, he enjoys playing video games, basketball and racquetball.

More from this Author

Follow Us