Tag Archives: Pipeline

Where did my request body data go?

Problem

The solution had several API controllers (see image above) that expected data to be posted in the body. Then for no reason the body data was null, and therefore the controller started throwing argument null exceptions, and the front end of course stopped working.

The issue was caused by a new custom HttpRequestProcessor (see image below), which was called in the httpRequestBegin pipeline.

private void ProcessApi(HttpRequestArgs args)
{
      using (var mem = new MemoryStream())
      {                
           HttpContext.Current.Request.InputStream.CopyTo(mem);
           HttpContext.Current.Request.InputStream.Seek(0, SeekOrigin.Begin);
                
           using (var reader = new StreamReader(mem))
           {
                mem.Seek(0, SeekOrigin.Begin);
                var body = reader.ReadToEnd();

                if (string.IsNullOrEmpty(body))
                    return;

                var requestBody = JsonConvert.DeserializeObject<RequestBody>(body);
                _setLanguageService.SetLanguage(requestBody);
           }
      }            
 }

It needed the data from the request body, for some reason the setting the position back to 0, did not work?

Therefore the controller got null instead of the data contained in the body.

Solution

Therefore it was necessary to copy the stream contents into a memory stream, read the data from that stream, then deserialize the class. See the solution below.

I hope this helps, and this issue was found Sitecore 8, with a lot of customization, patches, code and modifications over the past 16 years.

Sitecore SPEAK – Pipelines

As promised here is a post about how to create a simple client side Sitecore SPEAK pipeline.

For an introduction to pipelines, see my first blog about Pipelines. I am going to create a pipeline which serves no purpose at all, it just writes “step 1”, “step 2” & “Step 3” to the console. There are 5 steps to implement a pipeline:

  1. Declare the pipeline
  2. Declare individual pipeline steps
  3. Add the steps to the pipeline
  4. Include JavaScript
  5. Execute the pipeline

How to declare a pipeline

Firstly you check if the pipeline is already declared, and if not you create it.


Sitecore.Pipelines.MyFirstPipeline = Sitecore.Pipelines.MyFirstPipeline ||
                                 new Sitecore.Pipelines.Pipeline("MyFirstPipeline");

Declare the step

Declare the pipeline step by creating an object which has a priority property and an execute function which accepts a context variable. The execute function is the where you write the code for this step, in this case log “step 1” to the console, or abort if the context.hasRun == true.


var step1 =
 {
   priority: 1,
   execute: function (context) {
     if(context.hasRun==true){
       context.aborted = true;
       return;
     }
     console.log("step 1");
   }
 };

The priority property defines the sequence that the steps are executed in, and as I mentioned in my previous post this is not ideal 😦 but Anders and I had an idea how to solve this so please read this great post by Anders.

But back to the point. If you want to abort a pipeline, you just have to set the property abort on the context to true, and then no more steps will be executed.

Add a step to the pipeline

Its easy to add a step to a pipeline, you just call the add method.

Sitecore.Pipelines.MyFirstPipeline.add(step1);

Not that it is a requirement, but I would suggest that all the code for a single step is contained in a single JavaScript file.


define(["sitecore" ], function (Sitecore) {
  Sitecore.Pipelines.MyFirstPipeline = sitecore.Pipelines.MyFirstPipeline || new Sitecore.Pipelines.Pipeline("MyFirstPipeline");
  var step1 =
  {
    priority: 1,
    execute: function (context) {
     if(context.hasRun==true){
       context.aborted = true;
       return;
     }
     console.log("step 1");
    }
  };
  Sitecore.Pipelines.MyFirstPipeline.add(step1);
});

Include JavaScript

Before we can call the pipeline we need to ensure that the JavaScript is loaded.
SPEAK wraps up the requireJS framework, so we can define which JavaScript files should be included.
I would recommend a single JavaScript file for each pipeline that is responsible for loading all the pipeline steps. Therefore when you want to execute a pipeline you only have to include one file. Also if you add steps to a pipeline you only have to update a single file and not all the places where the pipeline is executed.

var basePath = "/-/speak/v1/mfp/";
define(
    [
        basePath + "MyFirstPipeline.Step1.js",
        basePath + "MyFirstPipeline.Step1.js",
        basePath + "MyFirstPipeline.Step1.js"
    ]
)

When creating pipelines I tend to use the following naming convention:

[Pipeline Name].[Step Name].js and the file that includes all the steps is called [Pipeline].js, for example the file structure for MyFirstPipeline would be as follows.:

file structe

BasePath

So how does Sitecore know where to look for the JavaScript files, and what is that base path?

If you take a look in the Sitecore.Speak.config file in the include folder, you will see there is a speak.client.resolveScript section, which defines a server side pipeline that is responsible for resolving scripts.

The Sitecore.Resources.Pipelines.ResolveScript.Controls processor is used to load all the scripts required by controls. It has a section where you can define one or more sources. Take a look at the source which has the category “mfp” which I added so that the JavaScript for the application is included correctly.

  • Category – used to match which source to use to locate files.
  • Folder – the folder to search.
  • Deep – should it search sub folders.
  • Pattern – pattern to select files in the folders.
<processor type="Sitecore.Resources.Pipelines.ResolveScript.Controls, Sitecore.Speak.Client">
  <sources hint="raw:AddSource">
    <source folder="/sitecore/shell/client/Speak/Assets" deep="true" category="assets" pattern="*.js" />
    <source folder="/sitecore/shell/client/Speak/Layouts/Renderings" deep="true" category="controls" pattern="*.js,*.css" />
    <source folder="/sitecore/shell/client" deep="true" category="client" pattern="*.js,*.css" />
    <source folder="/sitecore/shell/client/speak/layouts/Renderings/Resources/Rules/ConditionsAndActions" deep="true" category="rules" pattern="*.js" />
    <source folder="/sitecore/shell/client/Business Component Library/Layouts/Renderings" deep="true" category="business" pattern="*.js,*.css" />
    <source folder="/sitecore/shell/client/Applications/MyFirstPipeline" deep="true" category="mfp" pattern="*.js,*.css" />
  </sources>
</processor>

This explains the mfp part of the base url (/-/speak/v1/mfp/) but what about the rest? The following setting specifies the prefix that should trigger the HTTP request customer handler for SPEAK.

<setting name="Speak.Html.RequireJsCustomHandler" value="/-/speak/v1/" />

Execute the pipeline

At last we are now ready to execute our pipeline, so we create the context, pass in the application and call execute. The context contains the pipeline specific information required by each step in the pipeline.
The first time the pipeline is executed all 3 steps are completed. The second time it will abort at the first step as the context property hasRun is set to true.


define(["sitecore", "/-/speak/v1/mfp/MyFirstPipeline.js"], function (Sitecore) {
 return Sitecore.Definitions.App.extend({
   initialized: function () {

   //clone the context, unless you want the changes to the context to be persisted
   var context = clone(this.currentContext);
   context.testAbort = false;

   //run the pipeline
   Sitecore.Pipelines.MyFirstPipeline.execute({ app: this, currentContext: context });

   //run the pipeline but it will abort
   context.hasRun= true;
   Sitecore.Pipelines.MyFirstPipeline.execute({ app: this, currentContext: context });
 }
 });
});

Well I hope you find this post helpful, as ever take it easy, Alan