Caching In MVC
In this post we will discuss about how we can improve the performance of out 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 when ever 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 time 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 recommend to use the most useful thing ‘Caching’. This will make sure that there is 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 a MVC project. As you all know when it comes to performance, our clients will never be satisfied. So we used to 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 wit 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 is already happened just by using Output Caching(In ASP.NET 5 it is ResponseCache). The view which is rendered recently wont fire the controller again if it is in the time limit period, it will just re show 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 when ever a user hits the controller it will hit the DB and fetch the data right? 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 withing 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.
Now we will create a control in our MVC application.
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 below.
[csharp]
public ActionResult Index()
{
return Content(DateTime.Now.ToString("T"));
}
[/csharp]
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 minute, what is the output you are getting?
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.
[csharp]
[OutputCache(Duration = 300, VaryByParam = "none")]
public ActionResult Index()
{
return Content(DateTime.Now.ToString("T"));
}
[/csharp]
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. That’s cool right?
Even though it is so cook, there is 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’s hit we need to go to the database right? So in simple words we can say that the caching is helping to reduce the amount of work done must be performed by our web server and database.
So contents are chached. Where?
Now we will see which are all the locations we can save the cache data. Usually the contents are cached in three locations.
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’.
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 in to the application it will show the country name as India. That’s correct. Now have cached these 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?
[csharp]
[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult Index()
{
User u = new User();
return Content(u.getUserCountry());
}
[/csharp]
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.
[csharp]
[OutputCache(Duration = 10, VaryByParam = "none", Location=OutputCacheLocation.Client, NoStore=true)]
public ActionResult Index()
{
User u = new User();
return Content(u.getUserCountry());
}
[/csharp]
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 these data in server.
Use of VaryByParam property
Now we are going to discuss an 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 links, an another view (GetEmployeeDetails) will show with all the details about that employee( Like account details, leave details, personal informations). 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.
[csharp]
[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult GetEmployee()
{
Employee e = new Employee();
return Content(e.getEmployees());
}
[/csharp]
[csharp]
[OutputCache(Duration = 10, VaryByParam = "empID")]
public ActionResult GetEmployeeDetail(int empID)
{
Employee e = new Employee();
return Content(e.getEmployeeDetails(empID));
}
[/csharp]
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.
[html]
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Admin" duration="86420" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
[/html]
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.
[csharp]
[OutputCache(CacheProfile="Admin")]
[/csharp]
That is all about the Caching. I will come with an another post which explains caching in ASP.NET 5, MVC 6 soon. Thanks for reading. Have a happy coding.
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?
A blog isn’t a blog without comments, but do try to stay on topic. If you have a question unrelated to this post, you’re better off posting it on C# Corner, Code Project, Stack Overflow, Asp.Net Forum instead of commenting here. Tweet or email me a link to your question there and I’ll definitely try to help if I can.
Kindest Regards
Sibeesh Venu