Tuesday, 11 September 2018

Sitecore Module - Dynamic Sitemap XML version 2.0

I have released updated and rewritten version of my Dynamic Sitemap XML module.Version 2.0 comes with better structure of the code and gives much more flexibility in extending it. Now it uses Sitecore Web index by default to improve the performance.

Whole code is hosted on GitHub just like before at https://github.com/ReoKzK/Sitecore.SharedSource.DynamicSitemap.


It can be added to solution by nuget package:

Install-Package Sitecore.SharedSource.DynamicSitemap -Version 2.0.0

Tuesday, 21 August 2018

HelixComponents - Gallery of frequently used website modules

I have released first part of my HelixComponents project. It's aim is to create reusable components that can be used across Helix-based projects.


Each module will be released as a separate repository, which is basically a Helix project. All of them can be taken from my repo at Github: https://github.com/ReoKzK/HelixComponents.
It is based on Helixbase and contains all of these modules.

Here are the first projects:

HelixComponents.Feature.Recommended

Contains modules used for content promotion

HelixComponents.Feature.Tabs

Tabs components - Work in progress

Soon I'm going to release more and fix any outstanding issues

Sunday, 10 June 2018

Sitecore 9 installation scripts

As Sitecore 9 installation is much different than in previous versions and we have now Sitecore Installation Framework, I would like to share with you my installation PowerShell scripts.

First of all, many thanks to George Chang for the Sitecore 9 install script which I based mine (https://blogs.perficientdigital.com/2017/10/23/how-to-install-sitecore-9-with-the-sitecore-install-framework/).

First thing you will need to do is have Solr installed. It is required from v.9.0 to have Solr running and on SSL. There is a great post by Jeremy Davis about installing Solr easily by his PS script - https://jermdavis.wordpress.com/2017/10/30/low-effort-solr-installs/.

After we have Solr installed and running on https we can start installing our Sitecore 9 instance.

We need to have Sitecore Installation Framework installed to our PowerShell. Here is the script that takes care of it:

 

And here is the Sitecore 9 installation script itself. There is a configuration object as first in the code, you can specify there Sitecore version to install, SQL Server credentials and Solr configuration.


All scripts are available on my GitHub: https://github.com/ReoKzK/Sitecore9-Installer


Saturday, 19 May 2018

SIF Sitecore 9 installation issue

A couple days ago I came across a problem while installing Sitecore 9.0.2 using SIF:

.Net SqlClient Data Provider: Msg 12809, Level 16, State 1, Line 5
You must remove all users with password before setting the containment property to NONE.

I was using MS SQL Server 2016 (13.0.4001.0). After opening Management Studio I realized that some databases were created already because at first run my script went to some point then failed. So the easy fix go go through this issue was just to remove these databases as they were only partially completed.

Saturday, 7 April 2018

Configuring Unicorn on Helix project

Setting up synchronization in Helix based solution is one of the most crucial things. With proper configuration all new projects will be easy to maintain and predictable. In this short post I will describe basics of configuring Unicorn.

Helix structure configuration

First of all we should have our Foundation.Serialization project configured. In this project we should install Unicorn - from the nuget feed.

We should have whole Helix items structure configuration here and this one should be synched as the first in the queue.


There is unicornSourceFolder variable which should be pointing /src/ folder of our app code. We can specify it for example in some patch in Project.Common project.


 

Abstract configurations

It is really good idea to have some basic configuration we can inherit from. It can be placed in for example Foundation.Serialization project.





Then we can use this abstract configuration in our projects




We do it by using extends parameter

extends="SitecoreCoffee.Base"

If our project is relying on some other, e.g. from Foundation layer, then we should specify it by dependencies parameter. Here it depends on whole Foundation layer by using asterix

dependencies="Foundation.*"

...but it could be as well list of comma-delimited configuration names

dependencies="Foundation.Search,Foundation.Extensions"

As I mentioned earlier, Foundation.Serialization configuration should be synchronized as first, so the our patch should go after that one:

patch:after="configuration[@name='Foundation.Serialization']"

Don't forget to put descriptive name and description attributes too.

Project-specific configurations

In Helix every project which requires some serialized Sitecore items, should have it's own Unicorn configuration. Above we created Feature.Search project configuration and there we put only project-specific items in the predicate

<predicate type="Unicorn.Predicates.SerializationPresetPredicate, Unicorn" singleInstance="true">
    <include name="SitecoreCoffee.Feature.Search.Templates" database="master" path="/sitecore/templates/Feature/Search" />
    <include name="SitecoreCoffee.Feature.Search.Renderings" database="master" path="/sitecore/layout/renderings/Feature/Search" />
</predicate>

Even if you're not using Helix you should consider creating several small configurations instead of one monolithic. It will be easier to synch only specific ones in Unicorn synch panel.





Monday, 12 March 2018

Using SitecoreController to change page startup

A few days ago I had to implement functionality that will check if external e-commerce system is healthy before any further page processing. I decided to prepare maintenance page in Sitecore and switch to it if there are problems with API. Here the problem appeared - how to make it clean and use already DIed services there?

I could use httpBeginRequest pipeline and put my processor just after Context.Item is resolved. Sounds alright but I wanted to avoid adding unnecessary processors and patches as much as I could.

Then I found really interesting post written by Marek Musielak:

Sitecore Item Controller - the hidden gem of Sitecore MVC https://www.skillcore.net/sitecore/sitecore-item-controller-and-page-rules
I decided I will go with this approach and utilize SitecoreController. Marek described precisely how to set up that new controller and where to refere it in template. Here I will describe how I used it.

Controller setup

My controller will be responsible for checking external commerce health before any rendering and API call is made. It should extend SitecoreController that exists in Sitecore.Mvc.Controllers namespace (Sitecore.Mvc assembly). I'm using there two services - one that wraps context item switching and second one for API calls. I found out that there should be only one parameterless constructor in this controller. Unfortunately then you can't inject services properly - only way is to use service locator antipattern!

Further, you should override Index() method and do your stuff there. I'm calling heartbeat service and if system is dead I'm switching context page item to maintenance page. I'm checking as well if maintenance mode was explicitly set in site settings item. And if we are in Experience Editor we don't want this switching to happen, so I'm checking for that option as well. At the end we need to call base Index() method.

Be aware: heartbeat check action must be fast as Flash or even faster. You don't want to add much more rendering time to page. Sometimes it's even better to do that check on client side, but that's more SPA approach. Just make sure it finishes in desired period of time and even drop the execution if it takes more! You can use async calls and cancellation tokens - here I found some nice article by Dave Paquette you can begin with, but that's surely something outside Sitecore: https://www.davepaquette.com/archive/2015/07/19/cancelling-long-running-queries-in-asp-net-mvc-and-web-api.aspx

Page template setup

As Marek described, we need to bind our controller with template's Standard Values to make it work.

Template using SitecoreController

And that's it, this functionality will run before any rendering start to be processed.


Whole implementation is available on my Helix examples and experiments project on GitHub:

ReoKzK/SitecoreCoffee https://github.com/ReoKzK/SitecoreCoffee/tree/master/src/Feature/Commerce/code

Monday, 27 November 2017

Custom Remote Events for Cache Rebuild mechanism

A couple of months ago I had to jump into a project for a while and I came across a problem with refreshing custom cache on content delivery servers. There was a custom cache mechanism that was running on each instance separately. It was relying on items based on specific template, every time one of these items was updated or created/removed, cache should be updated. I found out that the best way to refresh that is to prepare custom remote event.

The problem

I had to make sure that after publishing specific items, cache will be rebuilt. My first thought was to use publish:end event, so I could check if one of that items was published. But here the problem with checking came out. There is a parameter of class Publisher that is put to EventArgs on position 0. Unfortunately, it doesn't contain any list of published items, just the root item:

publisher.Options.RootItem

...or maybe fortunately, for huge amount of items published :) Anyway, if we are relying only on this property, we need to go through all items recursively to find the specific one:

publisher.Options.RootItem.Axes.GetDescendants().Any(x => x.TemplateID.ToString() == SpecificTemplateId)
You might see that here, on some publish events, using Axes and GetDescendants() is not very good idea (most of times it's not!). And we need to keep in mind that RootItem will be null if user ran full site publish...

Improve the performance

Okay, maybe some better ideas? Yes. There is an event called publish:itemProcessed that is fired every time an item is processed during publish. We can use it to find if currently processed item is based on specific template and then set some flag.


Flag used here will be static property of the event handler class:

/// <summary>
/// Static flag that indicates if any specific item was published
/// </summary>
protected static bool SpecificItemWasPublished = false;


After all items have been processed, the publish:end event will be raised. Here we can check if flag is set to true and run cache refresh action. This solution will work gracefully on single server application, but on CM/CD separated instances it will work only on Content Management server. We need to work out a better solution using custom remote events.

Using custom remote event

Custom remote event will be the best option to solve this problem. Our cache refreshing system will work like this
  1. While publishing we check if specific item is published - on publish:itemProcessed event. If there is one, we set up the flag.
  2. When publishing finishes (publish:end) we check the flag. If flag is set up, we raise cache rebuild event
  3. Cache rebuild event will raise remote event for cache rebuild.
Using this approach all hard work, like checking specific item published, will take place on the local server, remote servers will just do what first told them. It all works using EventQueue.

1. Class for remote event representation
First thing that we will need will be class that represents an event. There is no base class to derive or interface to implement, it can be plain class but members need to be serializable. In our example we will have a boolean flag that will indicate if full rebuild is needed.

2. Event raiser class
Next we will need a handy class that will be able to raise the event locally and add request to Event Queue for raising it on remote servers.

3. Pipeline processor for initializing event subscription
We need to create a pipeline processor that will subscribe to those remote events.

4. Event handlers class
This class will contain our event handlers. As described earlier OnItemProcessed will check if currently processed item is based on specific template and set up flag if found. OnPublishEnd will check that flag when publishing is finished and raise cache rebuild event using prepared earlier event raiser. Last event handler OnCustomCacheRebuild will do the actual call to index mechanism for cache rebuild.

5. Sitecore config patch
At last we have to bind all event handlers and processors into Sitecore. This Sitecore config patch does that:
 
And that's all, with all these parts our system is ready to use.


Testing solution 

To test our solution we need to set up two Sitecore instances on our local machine, first for CM role, latter for CD role.They need to have different InstanceName properties set in App_Config\Include\ScalabilitySettings.config.

<setting name="InstanceName">
  <patch:attribute name="value">SitecoreCoffeeCM</patch:attribute>
</setting> 

As well those two instances need to use the same databases.

After setting up those instances and publishing item based on specified template on CM server, there will be new record created in Core database in EventQueue table:

Id:            C3386293-8E1B-4EBB-A490-D57DC663E61B
EventType:     SitecoreCoffee.Foundation.RemoteEvents.Events.CacheRebuildEvent, SitecoreCoffee.Foundation.RemoteEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
InstanceType:  SitecoreCoffee.Foundation.RemoteEvents.Events.CacheRebuildEvent, SitecoreCoffee.Foundation.RemoteEvents, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
InstanceData:  {"FullRebuild":true}
InstanceName:  SitecoreCoffeeCM
RaiseLocally:  0
RaiseGlobally: 1
UserName:      sitecore\admin
Stamp:         0x0000000000032E9E
Created:       2017-11-21 23:20:01.267

And as well on those two instances cache will be rebuilt:

ManagedPoolThread #2 23:20:01 INFO  CacheRebuildEventHandler: Rebuilding the cache.
ManagedPoolThread #2 23:20:01 INFO  CacheRebuildService: Cache rebuilt (full: True)
ManagedPoolThread #2 23:20:01 INFO  CacheRebuildEventHandler: Cache rebuilt in 0 seconds.

Summary

Solution described above explains how to use custom events in Sitecore to create efficient mechanism that will rebuild cache on local and remote servers, when specific item is published. It can be used to perform any other type of action that will require additional activity taken on remote servers.

Full code is available in my Helix solution here: https://github.com/ReoKzK/SitecoreCoffee

Happy Sitecoring!