Category Archives: SPEAK

Sitecore SolR Sorting Challenge

As I promised in my last post (please read it first) here is a solution to address the SolR sorting issues.

The Problem

The issue is that different pages, usually have different date fields to represent how they should be sorted and if we want to adhere to the Helix principles, the Solr feature must NOT KNOW ABOUT PAGE TYPES.

For example, a news page will have a news date, calendar event might use the start date and an some page will not have a date field and therefore will have to use created and or updated.

Typically, I see solutions that deal with this issue at retrieval time i.e. index all the different fields and then have a specific “order by” clause for each page type.

The biggest disadvantages of this approach is that you cannot sort a list with different page types i.e. get the 10 latest items that are either news, event or articles.
In addition, you have to manage all the different order by clauses. Which will destroy the Indexing/SolR abstraction as you will have to expose the IQueryable<T> in order to apply the order by clause.


I prefer to deal with the sorting issue at indexing time and have a single dedicated SolR field which is used to sort all item types. This allows you to sort news, articles, calendar events, etc. in the same way.

You still must deal with the issue that the SolR implementation should not know about which field to use for a give item type. To overcome this issue we use a configuration file that defines the mapping between an item of a specific type and which field to use for sorting.

Template to Field Mapping

The following configuration defines which field should be stored for sorting for each item template, if a field mapping is not defined, the item updated value is used.

In sitecore,  it is easy to map the configuration below to a C# class (i.e. SortFieldMappingRepository) for more information, about how to do this see my blog post on Structured, Type Safe Settings in Sitecore.

<configuration xmlns:patch="" xmlns:environment="" xmlns:role="">
				<SortFieldMappingRepository type="Feature.SolRIndexing.Infrastructure.ComputedFields.Sorting.SortFieldMappingRepository, Feature.SolRIndexing" singleInstance="true">
					<mappings hint="raw:Add">
						<!--News, NewsDate -->
						<sortFieldMapping templateId="{AE6B4DF2-DF36-4C6D-ABDA-742EE6B85DE9}" sortFieldIdId="{3D43D709-DFAE-4B4F-8CB2-DF80D9B83857}"/>
						<!-- Calander, StartDate-->
						<sortFieldMapping templateId="{A8DD1F59-08AB-4BF0-BE76-8873A8F00628}" sortFieldIdId="{6369AC75-036B-48D8-95E2-F16998F8E777}"/>
						<!-- Video, VideoDate -->
						<sortFieldMapping templateId="{3D9D8B7A-FCB2-459B-908B-1E31F0C975FB}" sortFieldIdId="{E9993C21-1EF0-4C30-83D4-5F69923CEC3E}"/>
						<!-- Article, ModifiedDate Field -->
						<sortFieldMapping templateId="{F6B599F4-11C4-4C65-B253-95F3C40EBA18}" sortFieldIdId="{DC6C0E49-1705-4F3E-80EF-83176E482DBC}"/>

Define the SolR index Field

Then we define the SolR index field used for sorting and specify that the SortComputedIndexField class is responsible for adding the sort date to the index.

					<fields hint="raw:AddComputedIndexField">
							<!-- Sorting-->
							<field fieldName="_sort" returnType="datetime" >Feature.SolRIndexing.Infrastructure.ComputedFields.Sorting.SortComputedIndexField, Feature.SolRIndexing</field>


The SortComputedIndexField class is responsible for providing the value for the sort field and it calls the CalculateSortDateService to determine the sort value.

namespace Feature.SolRIndexing.Infrastructure.ComputedFields.Sorting
    public class SortComputedIndexField : AbstractComputedIndexField
        private readonly CalculateSortDateService _calculateSortDateService;

        public SortComputedIndexField(CalculateSortDateService calculateSortDateService)
            _calculateSortDateService = calculateSortDateService;

        public SortComputedIndexField()
            _calculateSortDateService = ServiceLocator.ServiceProvider.GetRequiredService<CalculateSortDateService>();

        public override object ComputeFieldValue(IIndexable indexable)
            Item item = indexable as SitecoreIndexableItem;
            if (item == null)
                return null;

            if (!item.Paths.FullPath.StartsWith(Constants.SitecoreContentRoot))
                return null;
            return _calculateSortDateService.CalculateSortDate(item);

The CalculateSortDateService class iterates over the field mappings, defined in the configuration and uses the field value for the date if the field is found, otherwise the updated value for the item is used.

namespace Feature.SolRIndexing.Infrastructure.ComputedFields.Sorting
    public class CalculateSortDateService
        private readonly SortFieldMappingRepository _sortFieldMappingRepository;

        public CalculateSortDateService([NotNull]SortFieldMappingRepository sortFieldMappingRepository)
            Assert.ArgumentNotNull(sortFieldMappingRepository, nameof(sortFieldMappingRepository));
            _sortFieldMappingRepository = sortFieldMappingRepository;

        public DateTime CalculateSortDate([NotNull] Item item)
            Assert.ArgumentNotNull(item, nameof(item));
            var mappings = _sortFieldMappingRepository.Get();
            if (mappings == null)
                return item.Statistics.Updated;

            foreach (var sortFieldMapping in mappings.Where(m => m != null))
                if (item.TemplateID != sortFieldMapping.TemplateId)

                Field dateField = item.Fields[sortFieldMapping.SortFieldId];
                if (dateField == null || string.IsNullOrWhiteSpace(item[sortFieldMapping.SortFieldId]))

                return new DateField(dateField).DateTime;
            return item.Statistics.Updated;

Sorting Extensions

The last part is to provide the ability to sort the result set and for this we introduce the SortDateSearchResultItem class and a few extensions methods to add sort ascending & descending.

namespace Feature.SolRIndexing.Infrastructure
    public class SortDateSearchResultItem : SearchResultItem
        public virtual DateTime SortDate { get; set; }

namespace Feature.SolRIndexing.Infrastructure.ComputedFields.Sorting
    public static class SortingQueryableExtensions
        public static IQueryable<T> SortDescending<T>(this IQueryable<T> query) where T : SortDateSearchResultItem
            return query.OrderByDescending(item => item.SortDate);
        public static IQueryable<T> SortAscending<T>(this IQueryable<T> query) where T : SortDateSearchResultItem
            return query.OrderBy(item => item.SortDate);

I hope this post will help, Alan

Sitecore SPEAK Insert Link Dialog – missing icons & sitecore tree – Don’t panic, U didn’t break it!!!!

I was upgrading a solution from 6.2 to 7.2 and it had a number of custom fields that no longer worked,  so I started to fix the code.

One of the custom fields showed the SPEAK  Insert link dialog and after making a lot of changes, I noticed that I had broken the SPEAK dialog, see below

Speak dialog....

I reviewed the changes I had made, and could not see what could have caused this issue? But to be on the safe side, I undid all of my changes, did a full build, etc and still I had the issue 😦

So I tried to open the dialog from a sitecore standard field, and it was also broken 😦


Whist starting to panic, after 5 minutes I noticed that the dialog had fixed itself!!!!

It appears that after a restart of the website the first time you open the “Insert link” dialog you have to wait 5 minutes for it to start working, after that it works straight away.




Sitecore Upload Media Dialog Hangs (System.UnauthorizedAccessException)

I have a customer that was experiencing that for some users the SPEAK upload dialog would hang (well was not finished after 30 minutes). It would appear that the image had been uploaded (see below) but it never finished.

Media Upload dialog hangs

After some investigation I found that the users did not have access (create, write or delete) to the media root folder, but the strange thing is that the item was created, but the blob field was empty?

item created in the root

With a lot editors around the world soon the root folder was full of items without images, when I checked the log I could see that in fact a System.UnauthorizedAccessException was being cast (see complete exception below) but not because the item could not be created, but because it was not possible to write to the item?

The user did not have the create permission, so why was the item created? And why does the upload dialog not warn about the user they can not create and or write to an item? so I reported this to Sitecore and they have registered it as a bug and the following hot fix is available:

Sitecore CMS 7.5 rev. 141003 Hotfix 431794-1

If you don’t want to install a support DLL and JavaScript an alternative workaround is to  switch to the non-SPEAK version of the Select Media dialog by performing the following steps:

  1. Edit the /App_Config/Include/Sitecore.Speak.Applications.config file;
  2. Comment out the following lines:
      <override xmlControl="Sitecore.Shell.Applications.Media.MediaBrowser" with="/sitecore/client/applications/Dialogs/SelectMediaDialog" />

Complete Exception

Exception: System.Web.HttpUnhandledException
Message: An unhandled exception occurred.
Source: Sitecore.Mvc
   at Sitecore.Mvc.Pipelines.MvcEvents.Exception.ShowAspNetErrorMessage.ShowErrorMessage(ExceptionContext exceptionContext, ExceptionArgs args)
   at Sitecore.Mvc.Pipelines.MvcEvents.Exception.ShowAspNetErrorMessage.Process(ExceptionArgs args)
   at (Object , Object[] )
   at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
   at Sitecore.Mvc.Pipelines.PipelineService.RunPipeline[TArgs](String pipelineName, TArgs args)
   at Sitecore.Mvc.Filters.PipelineBasedRequestFilter.OnException(ExceptionContext exceptionContext)
   at System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList`1 filters, Exception exception)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at Sitecore.Mvc.Controllers.SitecoreActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.<>c__DisplayClass22.<BeginExecuteCore>b__1e()
   at System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action)
   at System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult)
   at Sitecore.Mvc.Routing.RouteHttpHandler.EndProcessRequest(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Nested Exception
Exception: System.UnauthorizedAccessException
Message: The current user does not have write access to this item. User: XXX\yyy, Item: Desert ({B1793B35-A61D-40AC-869F-4AD66A752234})
Source: Sitecore.Kernel
   at Sitecore.Data.Items.ItemEditing.BeginEdit()
   at Sitecore.Resources.Media.MediaData.SetBlobStream(MediaStream mediaStream)
   at Sitecore.Resources.Media.Media.SetStream(MediaStream mediaStream)
   at Sitecore.Resources.Media.MediaCreator.AttachStreamToMediaItem(Stream stream, String itemPath, String fileName, MediaCreatorOptions options)
   at Sitecore.Resources.Media.MediaCreator.CreateFromStream(Stream stream, String filePath, MediaCreatorOptions options)
   at Sitecore.Controllers.MediaController.Upload(String database, String destinationUrl)
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

Missing dialog’s after upgrading to Sitecore 7.5

After upgrading to Sitecore 7.5 there where a number of SPEAK dialog’s (select media dialog, insert item link, etc) that would open and show the front page of the website?

I eventually tracked it down to they fact that their where a number of duplicated SPEAK items in the core database see the image below and the fact that the solution had some custom code which showed the front page if an item has no renderings defined (not a good idea).



I believe that whist upgrading a update package failed and or did not remove the unused items.


Delete all the items that have the folder icon, and then all the dialog should work again, of course take a backup of the items before deleting them.

Is it time to change the item structure of sitecore?

I hope with this blog to start a discussion about how we structure non-content items within sitecore. It is not about Component based architecture, that is just to set the context.

Sitecore item structure has always been very type orientated, see below. Where the content is structured by type instead of its logical grouping (component) i.e. you have to store the templates under the template folder, sub layouts under the sub layout folder, etc.

by type

For many years I have used component architecture where the logical grouping is more important than type i.e. Function before type. Use “Agile design principle”, where functionality is logically grouped based on cohesion. Focus on re-usability, maintainability and releasable.

by comp

It provides a good way to model a websites, as a website typically consist of one or more pages types, where each page type contains a number of components. The image below helps identify typical components.

break down

Each component usually consists of a number of non-content items i.e. layouts, templates, renderings, media, settings, look up values, etc.

Whist the visual studio project for the component can group the related files (C# classes, sub-layouts, layouts, XSLT’s, images, etc.)  prior to Sitecore 7.x this is not possible for template, layout, etc. items, they have to be stored under their respective root item, which causes items being fragmented throughout the item structure.

To assists in locating items related to a component, we are forced to use folder naming conventions to help track where a components items are located:

  • Templates                 /sitecore/templates/components/[COMPONENT NAME]/….
  • Sub-Layouts             /sitecore/layout/sublayouts/components/[COMPONENT NAME]/….
  • Renderings               /sitecore/layout/renderings/components/[COMPONENT NAME]/….
  • Layouts                    /sitecore/layout/layouts/components/[COMPONENT NAME]/….
  • Media Library          /sitecore/media library/components/[COMPONENT NAME]/….
  • Data source items (i.e. drop down values for the component) – usually specific to the implementation/component

SPEAK/ROCKS sets non-content items free!

Since the release of SPEAK and if you use Sitecore Rocks it is possible to store your template, layouts items etc. outside their respective root folder 🙂

This is in fact the philosophy and best practices for SPEAK where each application must be self-contained and store all templates, layouts, data source items, etc. under the root application item.

The only exception to this, is the dictionary items which must be stored under the dictionary item, please Sitecore can you fix this 🙂

This afore mention approach has the following advantages

  • Each component is self-contained an isolated from other components.
  • It is easier to maintain as all the items are grouped together and not spread out throughout the tree structure.
  • Easier to remove a component as you only have to delete a single root item.
  • Easier to move a component from one website to another, as you only have to take the root and its children.

One issue it does not help with is if a component modifies the Sitecore client as that is defined in the core database.

So if we move to a SPEAK based structure for non-content items it could be as follows:

  • Templates               /sitecore/components/[COMPONENT NAME]/templates/….
  • Layouts                    /sitecore/components/[COMPONENT NAME]/layouts/….
  • Sub Layouts            /sitecore/components/[COMPONENT NAME]/sub layouts/….
  • Renderings              /sitecore/components/[COMPONENT NAME]/renderings/….
  • Media                       /sitecore/components/[COMPONENT NAME]/media/…
  • Data Source values /sitecore/components/[COMPONENT NAME]/data source/….
  • etc.                           /sitecore/components/[COMPONENT NAME]/[…]/….

I have not had the opportunity to try this with a customer and the only issue holding me back is that it requires the use of Sitecore Rocks as the Sitecore client itself does not support templates/layout items outside of their folder.

I would love any feedback about the idea of moving templates, etc., out of their respective root folders for a web site, and not just for SPEAK applications.

How to kill Sitecore with a Database connection

Well it’s been a while since my last blog due to the summer holidays and the fact that we have been very busy at Pentia.

Anyway here is my next installment in my “How to kill Sitecore” trilogy.

We recently took over a website that was having a lot of performance issues, and when I looked in the log files I noticed that the database connections were timing out.

So initially investigated if there was an issue with the SQL server, but after profiling and monitoring the database it appeared to have no performance issues, but I noticed that some of the exceptions were coming from the Heartbeat task.

What I believe the heartbeat tasks does among other things is to establish a connection for all the connections defined in the connections section, so that when the first request comes in the database connection is ready to retrieve the data from the SQL server.

The solution had a lot of include files some of which defined connections to databases that no longer existed.

So what happens when you have 4 connection strings that contain a reference to a databases that does not exists, well the hearth beat runs every minute and therefore creates 4 new connections every minute.

The connections were setup to timeout after 20 minutes which meant that after 20 minutes the heartbeat task had created and was waiting for 80 connections.

The problem is that the default max number of connections is 100, which left only 20 connections for the actually data providers that were configured correctly and when the site was busy this was not enough so they started to timeout,  which in turn caused the site to run very slowly 😦

To be honest it would of helped and been a lot quicker to find this error if .NET cast an CONNECTION POOL HAS REACHED IT MAX!!

But once this issue was found and I removed the unused connections, the site ran a LOT faster.

Sitecore SPEAK Control view life cycle


We implemented a custom data source control that retrieves messages from a web service. The data source has a number of properties, some of which are bound to other SPEAK controls for example:

  1. Sorting – Bound to List Control
  2. Search Text – Bound to Text box
  3. Message Type – Drop down

Therefore we need to wait until all the bound properties are set before we call the web service to avoid unnecessary web service calls.

Solution 1

In the model we detect when the last property is bound (i.e. its value changes from empty to some value). In this case we used the MessageType when it contained a value it was assumed it was OK to call the web service.


This worked until the server side control code was re-factored and the following code was called first in the constructor and not last:

  parametersResolver.GetString("MessageType", "messageType");

The “Get String” function is responsible for generating the data-sc-bindings attribute of the control, which defines the bindings and the order they are bound (probably requires another post to explain all the magic that SPEAK does here).

Therefore as this was now called first, not last, each time the search text, sorting was bound another web service call was made. We could not detect if search text or sorting parameters had been bound or not as either of these properties can contain an empty string. It is not a great strategy to check all the properties and try to determine if they are bound or not and or rely on the order they are bound.

Therefore I investigated the life cycle to determine if there is an event, trigger, etc. I could use to determine when binding for a control is completed.

Control View life cycle

The life cycle for a control’s view is implemented as a pipeline (see my previous post about pipelines). The pipeline defines 5 steps:

  1. Initialization – call the view’s initialize function
  2. Applying Cross Binding – Bind all the properties for the control, and child controls that have bindings.
  3. Before Render – If the view declares a beforeRender function it is called.
  4. Render – If the view declares a render function it is called.
  5. After Render – If the view declares a afterRender function it is called.

Solution 2

A very simple solution was to add a beforeRender function to the view (see image below) and set the isReady to true and call Refresh on the Model.

As beforeRender  is called after all the bindings are bound, the refresh function only needs to check if isReady is true before calling the web service. The Refresh function has to check isReady as it is called each time a property changes and or the first time it is bound.

before Render

Sitecore SPEAK Uploader File types

In a previous post I introduced the Uploader control, since then I noticed it wasn’t possible to attach pdf’s and or any other file type that was not an image.

Each time I uploaded a pdf file, it would put a red boarder around the file, and no item was created in Sitecore.


ImageTypes – Setting

After some investigation, I found that the ImageType setting in the web.config defines what image (files) types can be uploaded via the SPEAK uploader control. If you append “pdf” for example it is possible to upload pdf’s.



I don’t like that I have to specify that PDf is an image type, as this might have other unwanted side effects. But when using the SPEAK uploader control, it creates the correct item type (i.e. PDF).


Sitecore SPEAK – Dialog Rendering

The standard way to add/create dialog’s in SPEAK is to add the Dialog Window control, and then add the controls required by the dialog to the Dialog Window’s placeholders.
This has a number of disadvantages

  • Each new page that requires the dialog has to add all the renderings/settings that the dialog requires.
  • The code related for the dialog is added to the code page.
  • If you need to add/remove controls from the dialog you have to update all the pages that use the dialog
  • If you have a page with a lot of dialog’s the page will have a LOT of controls and all the code

In order to address the afore mentioned issues and enable reuse of dialog’s across a number of pages, we introduced the concept of a Dialog Rendering item; which contains all the renderings required by the Dialog, and defines its own sub-page code which contains the code required by the dialog.
In this blog we will create a attachment dialog, as the uploader control that comes with SPEAK is very cool (look out for an upcoming blog post)..

attachment dialog

Adding/showing a dialog

There are a 4 steps in order to add and then show a dialog:

  1. Create the Dialog Rendering Template. (Whilst this is not required, as you could add the layouts to any item, I would strongly recommend defining a template).
  2. Create the Dialog Rendering item
    1. Add the Dialog Window Control and add the required controls to the Dialog Window placeholder.
    2. Add a SubPageCode control and create the JavaScript which provides the functionality required by the dialog.rendering item
  3. Add the dialog to the page using Client side insert renderings.
    1. The guid is the rendering item id (i.e. the attachment item defined in step 2).
    2. Then save the dialog in the subpage controls list with a unique name.
contextApp.insertRendering("{26D93861-13E8-4416-8319-0D03094A19CB}", { $el: $("body") }, function (subApp) {
        contextApp["showAddAttachmentDialog"] = subApp;


  1. To show the dialog the show function on the DialogWindow control has to be called. There are a number of ways this could be achieved, but I decided to implement it as follows
    1. In the initialize function for the dialog (SubPageCode JavaScript), set up an event handler to listen for a show event i.e. add:attachment:dialog:show.
    2. Define a showDialog function which calls the DialogWindow.Show().code
    3. To show the dialog, trigger the event and pass the in the required & paramter

Context Issue

The dialog does not have access to the page’s context and controls; therefore you pass the required context via the event parameters.
This in fact reduces dependencies as the only dependency is the event parameters; therefore the dialog is not aware of where it is called from.

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) {
       context.aborted = true;
     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.


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) {
       context.aborted = true;
     console.log("step 1");

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/";
        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


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" />

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