Sitecore sublayout caching vary by cookie

In Sitecore you can control the caching of your sublayouts in many different ways.

Caching parameters

Caching parameters

Checking the “Cacheable” box allows you you vary the cache by data (data source), device, login (anonymous users have a different cached version from named users), param (item parameters), query string or user (each user has his own version).

Caching is an area that hasn’t changed much since Sitecore 5, which is why this code should work on any Sitecore version. However, For caching in MVC, Sitecore have implemented a different approach. See CUSTOM CACHE CRITERIA WITH MVC IN THE SITECORE ASP.NET CMS by John West for more information.

But what if you wish to vary the cache on another parameter, say, the contents of a cookie?

My colleague, Niclas Awalt, solved this for me a while ago.

STEP 1: SETTING UP SITECORE

First we need to define the name of the cookie to vary by. This is done in the “Parameters” field on the sublayout:

Parameters

The “VaryByCookie” defines my caching key, and the “Mycookie” defines the cookie to vary by.

STEP 2: CREATE A CUSTOM SUBLAYOUT

This custom sublayout contains the code that determines if the sublayout is cacheable, and if the “VaryByCookie” value is set, and if so, creates a new cache key based on the contents of the cookie:

using System.Collections.Specialized;
using System.Text;

namespace MyNamespace
{
  public class CustomSublayout : Sitecore.Web.UI.WebControls.Sublayout
  {
    private string _varyByCookies;
    private string VaryByCookies
    {
      get
      {
        return _varyByCookies ?? (_varyByCookies = GetVaryByCookiesParameter());
      }
    }

    public override string GetCacheKey()
    {
      Sitecore.Sites.SiteContext site = Sitecore.Context.Site;

      if (!Cacheable)
        return base.GetCacheKey();

      if (site != null && (!site.CacheHtml))
        return base.GetCacheKey();

      if (SkipCaching())
        return base.GetCacheKey();

      if (string.IsNullOrEmpty(VaryByCookies))
        return base.GetCacheKey();

      var cacheKey = base.GetCacheKey() + BuildCookieValueString();
      return cacheKey;
    }

    private string BuildCookieValueString()
    {
      StringBuilder stringBuilder = new StringBuilder();
      foreach (var cookieName in VaryByCookies.Split('|'))
      {
        stringBuilder.Append(GetCookieValue(cookieName, "0NoValue0"));
      }
      if (stringBuilder.Length > 0)
        stringBuilder.Insert(0, "_#cookies:");
      return stringBuilder.ToString();
    }

    private string GetCookieValue(string cookieName, string defaultValue)
    {
      var cookieValue = Context.Request.Cookies[cookieName];
      return string.Concat(cookieName, cookieValue == null ? defaultValue : cookieValue.Value);
    }

    private string GetVaryByCookiesParameter()
    {
      NameValueCollection parameters =
        Sitecore.Web.WebUtil.ParseUrlParameters(this.Parameters);

      return parameters["VaryByCookie"] ?? string.Empty;
    }
  }
}

STEP 3: HOOK UP THE NEW SUBLAYOUT:

Next step is to replace the Sitecore Sublayout rendering control with our own.

First, create a small rendering type class:

using System.Collections.Specialized;
using System.Web.UI;

namespace MyNamespace
{
  public class CustomSublayoutRenderingType : Sitecore.Web.UI.SublayoutRenderingType
  {
    public override Control GetControl(NameValueCollection parameters, bool assert)
    {
      CustomSublayout sublayout = new CustomSublayout();

      foreach (string name in parameters.Keys)
      {
        string str = parameters[name];
        Sitecore.Reflection.ReflectionUtil.SetProperty(sublayout, name, str);
      }

      return sublayout;
    }
  }
}

Then, in the web.config, in the <renderingControls> section, call our new sublayout rendering control:

<renderingControls>
  <control template="method rendering" type="Sitecore.Web.UI.WebControls.Method, Sitecore.Kernel" propertyMap="AssemblyName=assembly, ClassName=class, MethodName=method" />
  <!-- OUR NEW RENDERING -->
  <control template="sublayout" type="MyNamespace.CustomSublayoutRenderingType, MyDll" propertyMap="Path=path" />
  <!-- OUR NEW RENDERING -->
  <control template="url rendering" type="Sitecore.Web.UI.WebControls.WebPage, Sitecore.Kernel" propertyMap="Url=url" />
  <control template="xsl rendering" type="Sitecore.Web.UI.XslControlRenderingType, Sitecore.Kernel" propertyMap="Path=path" />
  <control template="webcontrol" type="Sitecore.Web.UI.WebControlRenderingType, Sitecore.Kernel" propertyMap="assembly=assembly, namespace=namespace, class=tag, properties=parameters" />
  <control template="xmlcontrol" type="Sitecore.Web.UI.XmlControlRenderingType, Sitecore.Kernel" propertyMap="controlName=control name, properties=parameters" />
</renderingControls>

Now, each time you create a sublayout, it will automatically be able to use the VaryByCookie parameter, and vary the cache based on the contents of the cookie.

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in c#, General .NET, Sitecore, Sitecore 5, Sitecore 6, Sitecore 7, Sitecore 8 and tagged , , , . Bookmark the permalink.

One Response to Sitecore sublayout caching vary by cookie

  1. Pingback: Sitecore sublayout caching vary by cookie | Dinesh Ram Kali.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s