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
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:

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: