Wednesday 24 February 2016

Pipelines - Sitecore development basics

Pipelines are very important mechanism in Sitecore. They organize processed tasks in a very clear, classified and highly customizable way.

Pipelines contain processors, which execute specified actions, one after one. Each processor can abort whole pipeline, so subsequent processors won't be executed.

Processor must contain Process() method that returns void and accepts single argument based on class Sitecore.Pipelines.PipelineArgs or its derivative.

public class CustomPipelineProcessor
{
    public void Process(Sitecore.Pipelines.PipelineArgs args)
    {
        // Your logic
    }
}

To make your processor work, you need to bind it to pipeline in configuration file. Let's look at the <httpRequestBegin> pipeline configuration (Sitecore 8.1):

<httpRequestBegin>
  <processor type="Sitecore.Pipelines.PreprocessRequest.CheckIgnoreFlag, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.EnsureServerUrl, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.StartMeasurements, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.IgnoreList, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.UserResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.DatabaseResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.BeginDiagnostics, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.DeviceResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.LanguageResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.CustomHandlers, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.FilterUrlExtensions, Sitecore.Kernel">
    <param desc="Allowed extensions (comma separated)">aspx</param>
    <param desc="Blocked extensions (comma separated)">*</param>
    <param desc="Blocked extensions that stream files (comma separated)">css,js</param>
    <param desc="Blocked extensions that do not stream files (comma separated)">*</param>
  </processor>
  <processor type="Sitecore.Pipelines.HttpRequest.QueryStringResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.DynamicLinkResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.AliasResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.DefaultResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.FileResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.DeviceSimulatorResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel" />
  <processor type="Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel" />
</httpRequestBegin>

As you can see, there are a list of processors in pipeline. Names are meaningful, there are processors which resolve current site, user, database, etc.

So when we want to put our processor to pipeline, we create configuration patch file:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor type="SitecoreExperiments.Common.Pipelines.CustomPipelineProcessor, SitecoreExperiments.Common" 
                   patch:after="*[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" />
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

In this example patch code, new processor is added to httpRequestBegin pipeline. It is added just after ItemResolver processor, beacuse I set it by this attribute:

patch:after="*[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']"
Setting this is not necessary, I just wanted to show that it can be achieved.

I made sure that my config patch is loaded last, so I named it SitecoreExperiments.Common.Pipelines.config and I put it in directory named Z_SitecoreExperiments in \Website\App_Config\Include. After checking configuration at /sitecore/admin/showconfig.aspx I am sure that my patch works as expected:


Object that is passed to function can be modified by each processor, so subsequent processors can rely on data that is added or resolved previously. We can create our own class that inherits from Sitecore.Pipelines.PipelineArgs and adds custom fields or, for example, use CustomData SafeDictionary property:

public void Process(Sitecore.Pipelines.PipelineArgs args)
{
    args.CustomData.Add("CustomPipelineProcessor""Hello, is it pipeline I've been looking for?");
}

Pipelines can be run from code using method CorePipeline.Run()

var args = new Sitecore.Pipelines.PipelineArgs();
Sitecore.Pipelines.CorePipeline.Run("customPipeline", args);
 
// - result will be "Hello, is it pipeline I've been looking for?"
String result = args.CustomData["CustomPipelineProcessor"].ToString();

Pipeline Profiler

There is also useful tool to diagnose pipelines that run in our solution. It is disabled by default, to enable it rename configuration include file Sitecore.PipelineProfiling.config.disabled to Sitecore.PipelineProfiling.config. This config has two settings:

<setting name="Pipelines.Profiling.Enabled" set:value="true" />
This enables whole profiling.

<setting name="Pipelines.Profiling.MeasureCpuTime" set:value="true" />
This enables CPU time measurement. By default this is disabled.

 It can be accessed by url /sitecore/admin/pipelines.aspx. 




Sunday 21 February 2016

Changing default page title for Sitecore Desktop, Launchpad and Content Editor

My client really wanted to change default page title for Sitecore Desktop view. I have found that I can change it for Launchpad - by Item /sitecore/client/Applications/Launchpad and field "BrowserTitle" in Core database:



But to change default Desktop name in page title in Sitecore 8 it is more tricky. Using only Sitecore, without changing application code, you can make it by changing /sitecore/system/Dictionary/D/Desktop on Core database. It will change browser title of website/sitecore/shell/default.aspx. I have tested that, and it works but for me it is very strange solution - it changes the proper translation of "Desktop" word!

As an alternative you can change the Title attribute of the FormPage node in the following file:
\sitecore\shell\Applications\Shell.xml - hightlighted as red:

<?xml version="1.0" encoding="utf-8" ?> 
<control xmlns:def="Definition" xmlns="http://schemas.sitecore.net/Visual-Studio-Intellisense">
  <Shell>
    <Favicon Src="/sitecore/images/favicon.ico" />
    <Stylesheet Src="Shell.css" DeviceDependant="true"/>
    <Stylesheet Src="Startbar.css" DeviceDependant="true"/>
    <Script type="text/JavaScript" src="/sitecore/shell/controls/SitecoreObjects.js" />
    <Script type="text/JavaScript" src="/sitecore/shell/controls/SitecoreWindowManager.js" />
    <Script type="text/JavaScript" src="/sitecore/shell/controls/lib/scriptaculous/scriptaculous.js?load=effects" />
 
    <Script type="text/JavaScript" language="javascript" key="TrackModified">
      scSitecore.prototype.setModified = function(value) {
        this.modified = false;
      }
    </Script>
 
    <FormPage Submittable="false" TrackModified="false" ForceGlobalHeader="true" Title="My Custom Desktop Title">
      <CodeBeside Type="Sitecore.Shell.Applications.ShellForm,Sitecore.Client" FrameName="Shell"/>
      <img ID="Wallpaper" src="" alt=""/>
      
      <Border KeyDown="ShowStartMenu" KeyFilter="c91">
        <Border Class="DesktopArea" ID="Desktop" ContextMenu="ShowContextMenu">
          <Border ID="Links" Click="ClosePopups" DblClick="Launch"/>
        </Border>
        <div class="scStartbar">
          <Startbar />
        </div>
      </Border>
    </FormPage>
  </Shell>
</control>

For Content Editor application you can do similar, in the file \sitecore\shell\Applications\Content Manager.aspx change highlighted string:
<title><%= Translate.Text(WebUtil.GetQueryString("he""My Website Content Editor")) %></title>
I hope that in next versions it will be more simple to customize, just like Launchpad, because some clients are very alerted to such details as title in the browser :)

Wednesday 17 February 2016

Sitecore Module - Quick Package

Creating packages in Sitecore is quite simple, but sometimes you need to quickly create simple package with one item. For this purpose I have created Sitecore Marketplace package with my new module Quick Package.

This module provides rapid package creation, with just few clicks. It doesn't replace Sitecore Package Designer just lets simple actions be done faster. Module adds context menu item for all Sitecore items:

There is also new button on Developer tab:

By clicking on these elements you will see a popup, where you can set name of created package. By default it is item name which is currently selected and current date and time. You can also uncheck 'Include descendants' checkbox if you want only selected item in package - not whole tree beneath.


I have published it on Sitecore Marketplace: https://marketplace.sitecore.net/en/Modules/Q/Quick_Package.aspx
Full source code is available on github: https://github.com/ReoKzK/Sitecore.SharedSource.QuickPackage