allBlogsList

Sitecore Caching and how it works in MVC solutions

September 23rd, 2016

Sitecore provides us an option to use caching for renderings to improve system performance and response time. Let’s discuss how the renderings are cached in MVC solutions. There were a lot of articles from fellow Sitecorians on how to cache renderings using VaryBy options. I wanted to see in action what’s happening in the background to fetch the cache value. This article outlines my experience of caching HTML output for a Controller Rendering.

There are multiple options you can choose from for caching your rendering as listed below. You also have an option to extend this functionality by building your own custom cache criteria. One of the examples to implement your own custom cache key is explained by John West [here](https://community.sitecore.net/technical_blogs/b/sitecorejohn_blog/posts/custom-cache-criteria-with-mvc-in-the-sitecore-asp-net-cms-john-west-sitecore-blog "Custom Cache Criteria with MVC in the Sitecore ASP.NET CMS | John West | Sitecore Blog").

VaryBy_Options

For every rendering request, Sitecore runs a processor to generate a cache key based on the selected VaryBy options using Sitecore.Mvc.Pipelines.Response.RenderRendering.GenerateCacheKey located in Sitecore.MVC assembly and defined in Sitecore.MVC.config.

Note: Cache Key is only generated if the rendering is marked as cacheable.

Let’s apply each one of the VaryBy options for the same controller rendering and see how the cache key is generated.

Case: Vary by Data

With Vary by Data being checked, the cache key is generated something like

controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#data:[Path of the Datasource Item]

Since, the path to each data source item is different, the output cache varies by change in Datasource.

Case: Vary by Device

With Vary by Device being checked, the cache key is generated something like

controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#dev:Responsive

We can output different cache keys for different Sitecore Devices.

Case: Vary by Login

With Vary by Login being checked, the cache key is generated something like

controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#ogin:False

We can output different cache keys based on if user is logged in or not.

Case: Vary by Parameters

With Vary by Parameters being checked, the cache key is generated something like

controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#parm:[Key=Value]

We can output different cache for the same rendering based on the different rendering parameters.

Case: Vary by Query String

With Vary by Query String being checked, the cache key is generated something like

controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#qs:[request.QueryString]

Case: Vary by User

With Vary by User being checked, the cache key is generated something like

controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#user:extranet\Anonymous

We can output different cache based on the user logged in.

Once the cache key is generated based on your selections, next time when you make a request to the same rendering, Sitecore checks if there is a cache key available in HTML cache. This happens as part of Sitecore.Mvc.Pipelines.Response.RenderRendering.RenderFromCache located in the Sitecore.MVC assembly defined in the same Sitecore.MVC.config.

         protected virtual bool Render(string cacheKey, TextWriter writer, RenderRenderingArgs args)
        {
            ...

            string html = htmlCache.GetHtml(cacheKey);
            
            if (html == null)
            {
                return false;
            }

            writer.Write(html);
            return true;
        }

You don't have to worry if you have the same logic applied to every site in a multi-site solution as Sitecore HTML cache is specific to each website.

You can clear the cache using [HOST_NAME]/sitecore/admin/cache.aspx or you can also clear it programmatically by using something like,

var htmlCache = CacheManager.GetHtmlCache(Sitecore.Context.Site);
var cacheKey = "controller::[Controller]#[Controller Action]_#lang:[Language Culture Code]_#dev:Responsive";
htmlCache.RemoveKeysContaining(cacheKey);

This has been tested and verified on Sitecore 7.2 Initial Release and Sitecore Experience Platform 8.1 Update 3.

As always, please test these changes on your development environment before applying it on Production.