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, whenever a use requests 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 similar 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 that 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 on 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 it with you all.
What is Caching?
As mentioned above, you can get the most out of performance improvement technique. 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 re show the one which is already rendered. It will cache the contents which are 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 right? But in this scenario, it is not needed to hit the DB again since the data will be the 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 below:
public ActionResult Index()
{
return Content(DateTime.Now.ToString("T"));
}
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 that within five minutes, we have hit the controller twice? Now here is the magic of output cache. Please change your controller code as follows:
[OutputCache(Duration = 300, VaryByParam = "none")]
public ActionResult Index()
{
return Content(DateTime.Now.ToString("T"));
}
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 a 5 minute duration. That’s cool right?
Even though it is so cool, 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’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 that must be performed by our web server and database.
So contents are cached. Where?
Now, we will see all the locations where we can save the cache data. Usually, the contents are cached in 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 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 from Ireland logged in to the application? Will it be good if we show India as his/her country? It does’t make any sense, right?
[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult Index()
{
User u = new User();
return Content(u.getUserCountry());
}
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:
[OutputCache(Duration = 10, VaryByParam = "none",
Location=OutputCacheLocation.Client, NoStore=true)]
public ActionResult Index()
{
User u = new User();
return Content(u.getUserCountry());
}
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 copies of these data in server.
Use of VaryByParam Property
Now we are going to discuss another scenario which explains the use of VaryByParam
property. Let us say an action called ‘GetEmployee
’ will return all the Employees
in our company. Now if we click on any employee links, another view (GetEmployeeDetails
) will show with all the details about that employee (like account details, leave details, personal information). 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:
[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult GetEmployee()
{
Employee e = new Employee();
return Content(e.getEmployees());
}
[OutputCache(Duration = 10, VaryByParam = "empID")]
public ActionResult GetEmployeeDetail(int empID)
{
Employee e = new Employee();
return Content(e.getEmployeeDetails(empID));
}
The above mentioned implementation will make sure the different Employee Details view are being generated for different users. Sound cool?
Cache Profiles
There is 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:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Admin"
duration="86420" varyByParam="none"/>
</outputCacheProfiles>
</outputCacheSettings>
</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:
[OutputCache(CacheProfile="Admin")]
That is all about the caching. I will come with another post which explains caching in ASP.NET 5, MVC 6 soon. Thanks for reading. Happy coding!
Conclusion
Did I miss anything that you may think is needed? Did you try caching yet? Have you ever wanted to do this? Could you find this post useful? I hope you liked this article. Please share 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.