Caching In MVC

In this post we will discuss about how we can improve the performance of our MVC application by using the technology Caching. Here I am using Visual Studio 2012. As you all know in MVC it is all about actions, so each and every time we are calling some actions according to the users request. For example, whenever a use request a view we will call the controller and get the result and bind the data to the view. Isn’t it? So what if a user is requesting the same view 50 times in 2 minutes? In normal cases, this won’t happen, but there are few situations which may be somewhat equal to what I said. In that case it is always recommended to use the most useful thing ‘Caching’. This will make sure that there are no actions which are not required will be happening within a time period.

So if a user already visited the same view within the time periods, the controller action won’t fire again if user calls the view again. It will return the same view which has been already rendered. Sounds cool? Yes, we will see how we can achieve this!. I hope you will like this.

Background

I am working in an MVC project. As you all know when it comes to performance, our clients will never be satisfied. So we used everything we have got to improve the performance. One thing we used was Caching. So I thought of writing an article related to that and share with you all.
What is Caching?

As I said above, it is performance improvement technique where you can get most of. It helps to avoid the unwanted or frequent actions which already happened just by using Output Caching (In ASP.NET 5 it is ResponseCache). The view which is rendered recently won't fire the controller again if it is in the time limit period, it will just reshow the one which is already rendered. It will cache the contents which is returned by the controller action.

Imagine that you have a controller which will return your debit/credit transaction from the database. What if the database is normally updating once in a week? Usually whenever a user hits the controller it will hit the DB and fetch the data. But in this scenario it is not needed to hit the DB again since the data will be same for a week. So we can set the Output Caching so that within the time interval the controller contents will be in cache so that the view can render the cached data.

How to enable Output Caching

We will create a simple application in Visual Studio first.

Caching In MVC
Caching In MVC

Now we will create a control in our MVC application.

Caching In MVC

So our controller is ready, now we need to create simple view and after that we will change our Index action in the controller as in the following code snippet:
  1. public ActionResult Index()  
  2. {  
  3.    return Content(DateTime.Now.ToString("T"));  
  4. }   

So we are returning the current time from the controller. Isn’t it? Now refresh your view frequently, let us say 2 times in 5 minutes, what is the output you are getting?

Caching In MVC

Caching In MVC
So have you noticed it within five minutes we have hit the controller twice? Now here is the magic of output cache. Please change your controller code as follows:
  1. [OutputCache(Duration = 300, VaryByParam = "none")]  
  2. public ActionResult Index()  
  3. {  
  4.    return Content(DateTime.Now.ToString("T"));  
  5. }  
Here we are setting the cache duration as 5 minutes (5*60 seconds).

Now if you run and do the same exercise you can notice that the controller will be hit only once in 5 minutes duration.

Even though it is so quick, there are some limitations too. As the memory becomes low, the cache data will be released. So that there won’t be cached data.

Here in our case, we just used a simple view which returns time from the controller. What if the controller has some database operations, for every user hit we need to go to the database, right? So in simple words we can say that the caching helping to reduce the amount of work done must be performed by our web server and database.

So contents are cached. Where?

Now we will see which are all the locations we can save the cache data. Usually the contents are cached in the following three locations:
  • Web server
  • Proxy server
  • Web browser

You can always set where you want to save the cached data, whether it is in server, client or both server and client by using location property. By default the location will be ‘any’.

Caching In MVC
There are few situations that we should not cache in server. Let me explain, suppose we have a controller which will return the country name of the user logged in to our application. Now I am from ‘India’, so when I logged into the application it will show the country name as India. That’s correct! Now I have cached this data in the server. So what will happen if a user form Ireland logged in to the application? Will it be good if we show India as his/her country? It doesn’t make any sense, right?

  1. [OutputCache(Duration = 10, VaryByParam = "none")]  
  2. public ActionResult Index()  
  3. {  
  4.     User u = new User();  
  5.     return Content(u.getUserCountry());  
  6. }  
So in short we can say that we should not cache any personalized data in the server.

So what is the fix for this? Simple, cache the data in client. To do that we can change our controller as follows.
  1. [OutputCache(Duration = 10, VaryByParam = "none", Location = OutputCacheLocation.Client, NoStore = true)]  
  2. public ActionResult Index()  
  3. {  
  4.     User u = new User();  
  5.     return Content(u.getUserCountry());  
  6. }  
To use OutputCacheLocation, you must include the namespace using System.Web.UI;

Have you noticed that we have set NoStore=true? This is to intimate the proxy server that should not save any copy of this data in server.

Use of VaryByParam property

Now we are going to discuss another scenario which explain the use of VaryByParam property. Let us say an action called ‘GetEmployee’ which will return all the Employees in our company. Now if we click on any employee link, another view (GetEmployeeDetails) will show with all the details about that employee (like account details, leave details, personal information, etc.). So if we save the cached view of GetEmployeeDetails, what will happen? For all the employees, it will show the same GetEmployeeDetails view right?

So we will change the controller actions as follows:
  1. [OutputCache(Duration = 10, VaryByParam = "none")]  
  2. public ActionResult GetEmployee()  
  3.     {  
  4.         Employee e = new Employee();  
  5.         return Content(e.getEmployees());  
  6.     }  
  7.     [OutputCache(Duration = 10, VaryByParam = "empID")]  
  8. public ActionResult GetEmployeeDetail(int empID)  
  9. {  
  10.     Employee e = new Employee();  
  11.     return Content(e.getEmployeeDetails(empID));  
  12. }  

The above mentioned implementation will make sure the different Employee Details view are being generated for different users. Sound cool?

Cache Profiles

There is an another way of achieving the caching, that is cache profiles, which is nothing but creating a tag in web.config file and apply that for different controllers. In this way you can have the same cache profile for different controls. And also it is easy to make any changes in the cache profile since it is just a tag in the web.config file. Any changes in cache profile will get applied easily. I found this is the most effective way of caching. We can do the cache profile as follows:

  1. <caching>  
  2.     <outputCacheSettings>  
  3.         <outputCacheProfiles>  
  4.             <add name="Admin" duration="86420" varyByParam="none" /> </outputCacheProfiles>  
  5.     </outputCacheSettings>  
  6. </caching>  

The above cache profile can be used for any admin control action which will be cached for one day (60*60*24). You can simply use this profile as follows:

  1. [OutputCache(CacheProfile="Admin")]  

That is all about Caching. I will come with an another post which explains caching in ASP.NET 5 and MVC 6 soon. Thanks for reading.

Conclusion

Did I miss anything that you may think which is needed? Did you try caching yet? Have you ever wanted to do this requirement? Could you find this post as useful? I hope you liked this article. Please share me your valuable suggestions and feedback.

Your turn. What do you think?

If you have any questions, then please mention it in the comments section.

Read this article in my blog here.