In this tutorial, you will learn how to create a custom output cache provider within an Episerver CMS-powered website. Out-of-the-box, the default cache provider will allow you to cache a complete page. Implementing this type of caching strategy will allow you to significantly improve your page performance. If you are building a very complex site, the default output cache might not do exactly what you need it to do. If you find yourself in this situation, this is the tutorial for you 🔥🔥🔥
When you build a website using the ASP.NET framework and Episerver CMS, it is possible to create a custom cache provider in order to get the caching strategy to work exactly how you need it. In this example, I am going to assume that you want to implement a donut caching strategy. A donut cache will give you a lot more control over how a page is cached. The issue with implementing a donut cache, is that the default output cache provider will not give you the control you need to implement it.
To implement a donut cache strategy within your site, you will need the ability to use the output cache to cache the HTML skeleton, combined with the ability to partial cache certain elements contained on that page with a different expiry period. In a normal full page strategy, you would decorate a controller that you want to cache with the
[OutputCache] attribute. The ASP.NET partial cache uses a key/value pair strategy using MemoryCache to cache elements contained on a page. To implement a donut cache we need to use a mix of both. Enabling the [
OutputCache] attribute will prevent you from implementing a donut cache as you will not be able to additionally partial cache anything. This is why if you want to create a donut cache, you need to go custom.
Creating A Custom Cache Provider
To create a custom cache provider in a normal vanilla MVC website, you would create a new class and inherit from
OutputCacheProvider. Implement the overrides and you should end up with a skeleton class that looks like this:
Next, you would register the new custom output cache. This is done within the
web.config. In here, you would need to set your default provider:
If you try and implement this code within an Episerver website, you will encounter two issues. First, the
set will never be hit by the debugger in Visual Studio (it didn't for me at least!!!). Second, you will encounter this error
When using a custom output cache provider like 'EPiServerOutputCacheProvider', only the following expiration policies and cache features are supported: file dependencies, absolute expirations, static validation callbacks and static substitution callbacks.
These errors occur because a website that is powered by Episerver CMS will use a slightly different caching approach. To create a custom cache provider within Episerver, you need to learn about
IObjectInstanceCache. In Episerver 8, the
IObjectInstanceCache interface was introduced to enable us to cache things (see Object caching for more details). With this interface and a little bit of configuration, we can intercept all the output cache requests without having to implement a custom OutputCacheProvider.
This benefits us in two ways. First, the debugger will now work and second, we can do all our configuration in code rather than the
web.config. The skeleton code for our custom provider should now look like this:
When implementing a custom cache in Episerver, you do not need to worry about the
web.config configuration in order to register the custom provider. Instead, within an Episerver powered website, you create an Initialization module and add the configuration in code. The code to do this is shown below:
Now when running this code and attaching the debugger, any breakpoints you add within
Get and the
Addwill be hit and any code inside of them will run 💥
The next issue that you will encounter is the
OutputCacheProvider not supported error. This error is thrown when you try and decorate a controller with the Episerver cache attribute and get it to work with your custom cache provider. When you build a custom cache in Episerver, you need to ensure certain Episerver cache dependencies are also run. If you do not set certain cache dependencies, the site will fail. To get around this issue you need to create a custom
OutputCache attribute, rather than use the vanilla .NET one of the out-of-the-box Episerver attributes. Within this custom attribute, you can add the logic required to fix the error.
After building this custom
OutputCache attribute, you will need to decorate all the pages and blocks that you want to cache within your solution with it. After making this fix, the cache provider should work error-free 😊. The code to create this custom attribute is shown below:
This code is doing a lot. It sets
VaryByParams, it adds
AddValidationCallback, it sets the current page object as well as setting the cache expiry time. I recommend you just copy this code into your solution without modifying it too much 😕
That concludes all the tweaks you will need to make in order to create a custom cache provider in Episerver CMS. Be prepared to jump through a few hoops to make this work. When implementing a custom output cache provider, Episerver recommends using object caching via the
IObjectInstanceCache interface. As Episerver requires certain dependencies to be set in order for caching to work, you won't be able to use the standard
OutputCache attribute in your project. Instead, you will need to create a custom attribute. Happy Coding 🤘