Episerver Caching - Creating Global Custom VaryByParams in your OutputCache

In the first post, I talked about enabling the output cache in your Episerver website to get the benefit of HTML caching in your solution in , http://jondjones.com/learn-episerver-cms/episerver-developers-guide/episerver-caching/episerver-caching-the-output-cache-explained/.  Now, in most website builds this will be all you need, however, when you start to work with more complex websites, like e-commerce solutions then you may need to start thinking about more bespoke solutions. Sometimes, when you cache your pages, you may hit the snag of caching the wrong thing.  Let's say you have a multi-lingual website and instead of having a unique page Url for each language, you have a single Url and in the code, you automatically switch the language context based on the user IP address.  When you enable output cache, the first time a page loads, the user comes from the UK and the UK version of the page is loaded and cached. Now a visitor from Sweden visits your page, he lives in Sweden and wants the Swedish version of the page.  As your website has cached the page in English, he will see the English version that has been cached. This is a bit shit and happens because out of the box Episerver/.NET uses the part/route of the page as the cache key, so if you have custom content depending on anything else, then you will see strange results being returned from your website. Instead of not caching anything, a better approach would be to cache a version of the page for each language.  To do this, we need to make a custom unique cache key that uses the country key as an identifier for the page.  In order to do this, we need to add a custom param in your output cache profile.  Another good example of when you might need to do this is when you use visitor groups. Say you have a basic visitor group that displays different content based on the user being authenticated or not.  If you cache the page based on the first request and a user is anonymous after he logs in, he would be served the cached version of the page, which would be the anonymous HTML. In today's guide, we're going to cover how to create a global param that will be added to any page request to any bit of content that has the OutputCache enabled.  In the next guide, I will write how to enable specific params to individual pages and blocks.

Configuring Your Custom Param in Episerver

The first thing we need to do in order to work with a custom param is to define it within Episerver.  This is done in the API episerver.config file:
<episerver xmlns="http://EPiServer.Configuration.EPiServerSection">
  <applicationSettings httpCacheability="Public"
                       uiEditorCssPaths="~/static/tinymce/css/editor.css" />
In here we add the httpCacheVaryByCustom property, and add our custom param name in.  Note, if you want to add more than one parameter, you need to separate them with a comma. paramone, paramtwo etc..

Setting The Param On Each PageRequest

The next step is to now populate the parameter on each page request. This is done in the Global.ascx file by overriding the GetVaryByCustomString() method.
        public override string GetVaryByCustomString(HttpContext context, string custom)
                if ("CountryCodeHash".Equals(custom))
                   var languages = HttpContext.Current.Request.UserLanguages;
                   if (languages == null || languages.Length == 0)
                       return null;

                   var language = languages[0].ToLowerInvariant().Trim();
                   return CultureInfo.CreateSpecificCulture(language).LCID;
            return base.GetVaryByCustomString(context, custom);
The code above is more "for example" purposes.  We override the GetVaryByCustomString and check if the currency vary by param request matches our custom param name.  If it does, do some logic and return a string with the unique cache key in it. IN the example above I grab the current culture for the request (in the real world I would be getting the IP address and checking MaxMind for the location), finding the culture code and then setting that as the unique key.


In today's guide, we've covered how we deal with situations when the output cache, caches the wrong thing.  When we find these scenarios and want to solve them on a global application level, we usually need to figure out what the unique things are on the page and then create a custom param in the output cache so.NET can create different HTML snippets to deal with the scenario. Adding a cache parameter is pretty straight forward; we define the key in the Episerver.config and then in the global.ascx we override the GetVaryByCustomString() method, check the request for our custom parameter and then perform the logic to create a unique key.

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

Back to top
var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-35662136-1']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'stats.g.doubleclick.net/dc.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();