Friday, October 20, 2017

Beginners Guide: Output caching in EPiServer


Output caching is not a new concept. There is a variety of project that people try to implement output caching, but how to do it in EpiServer?

What is Output caching?

The main purpose of using Output Caching is to dramatically improve the performance of an ASP.NET MVC Application. It enables us to cache the content returned by any controller method so that the same content does not need to be generated each time the same controller method is invoked. 

Why using output caching?

Output Caching has huge advantages, such as:
*Reduces the load on the server because there is no need to generate the results again
* Reduces the load on DB (same reason)
* Faster response

How it is done on MVC?

OutputCacheAttribute class has been implemented in System.Web.Mvc class and can easily being used simply by decorating the Controller with [OutputCache]. There are different variations for using it, which I am not going to discuss now, but you can read more in here.

What is the problem? Lets use it on EpiServer.

Although [OutputCache] attribute works fine for MVC applications, there are some functionalities that are specific to CMS systems. Let me elaborate more with an example:
- You have a page on your CMS and someone tries to view it for the first time. The MVC engine will try to generate the results and then save in in cache.
A second later, another person requests the same exact page. As you've guessed the MVC will receive the request and since it has it on its cache, it will respond with the same exact results.
- On the next step the editor change something on the page and publish it, but s(he) will see the same exact results as before since MVC doen't know about the change and will still return the same response. This also happens for the next people whom request the same page.

So to summarize we have 2 big problem:
1- content should not be cached for the editors
2- After publishing a page the old cache should be invalidate and the whole process should go through

How to fix it?

To fix the problems by yourself you need a lot of knowledge about EPiServer and you need some time to implement it. Luckily EPiServer has implemented their own ContentOutputCacheAttribute that will handle those for you :)

Simply add ContentOutputCache on top of your action 

 public class MyPageController : PageController<PageType>

   [ContentOutputCache(Duration = 3600, VaryByCustom = "*")]

   public ActionResult Index(StartPage currentPage)

Handle your GetVaryByCustomString in your Global.asax and you are good to go

public class EPiServerApplication : EPiServer.Global

 public override string GetVaryByCustomString(HttpContext context, string custom)

What to put into the GetVaryByCustomString depends on your setup, but one simple example could be returning the AbsoluteUri of the page. This way, different pages will differ, language versions will be handled automatically (since the AbsoluteUri will be different regardless of your routing config) but be aware that the personalization will not work since the AbsoluteUri is the same for all different users.

 public override string GetVaryByCustomString(HttpContext context, string custom)
        return context.Request.Url.AbsoluteUri;

****Very Important!!!!

ContentOutputCache will not work, unless you have the httpCacheExpiration in your web.config.
Simply go to your webconfig>
configuration>episerver>applicationSettings and make sure that it has properties for httpCacheability and httpCacheExpiration.

It should be something like this:

    <applicationSettings httpCacheability="Public" httpCacheExpiration="0:10:00" .... />