Introduction
ASP.NET 5 supports a couple of caching mechanisms to improve the performance and responsiveness of applications. Here are few options to implement cache at various levels.
- Response Cache
- In Memory Cache
- Distributed Caching in SQL Server or In memory cache server
Currently ASP.NET 5 does not support Output Caching but it will be added in a future version. In this article we will explore Response Cache and In Memory Cache.
Response Cache
Response Caching adds cache related header in response from application if we decorate ResponseCache attribute to Action, Controller or Global level. ResponseCache
does not store HTTP response in server unlike Output Cache in prior versions of ASP.NET. It just adds the "Cache-Control" header in response, now it's the client's choice to cache the response in the browser or some intermediate server, if any. It can reduce the number of server roundtrip if the browser or cache server cached the previous response and server to any subsequent request. In this example, we have decorated ResponseCache
Action with the "ResponseCache
" attribute which takes the Duration
parameter.
[ResponseCache(Duration =60)]
public ActionResult ResponseCache()
{
return View("Index");
}
And in response we are seeing that the Cache-Control header has added in HTTP response
The Value of the Cache-Control header could be Public, Private or no-cache. Let’s discuss each one of them.
Public
Indicates that the response is allowed to cache by any caching mechanism. Mostly if the page is independent of user then we can make it publicly cacheable.
Private
The value of Cache-Control header is "privte," which means it will not be cached by any intermediate cache server. We can specify "Location = ResponseCacheLocation.Client
" along with ResponseCache
to make it private.
[ResponseCache(Duration =60 , Location = ResponseCacheLocation.Client)]
public ActionResult ResponseCache()
{
return View("Index");
}
In response, we are seeing that the value of the "Cache-Control" header is private. So the response is allowed to cache by only the user’s private area, like the Browser.
No Cache
If we don’t want to cache a response in any cache layer, we can specify the Location
value as none. Here is example code.
[ResponseCache(Duration =60 , Location = ResponseCacheLocation.None)]
public ActionResult ResponseCache()
{
return View("Index");
}
Additional HTTP headers used for caching include "Pragma" and "Vary", which are described below. Learn more about Caching in HTTP from the specification.
Attributes of ResponseCache
The ResponseCache
attribute supports many parameters, in this section we will understand each one of them.
Duration: Type int
The maximum time (in seconds) the response should be cached. Required unless NoStore
is true.
Location: Type ResponseCacheLocation
The location where the response may be cached. May be Any, None, or Client. Default isAny. Based on this value, the value of the "Response-Cache" header changes.
NoStore :Type bool
Determines whether the value should be stored or not, and overrides other property values. When true, Duration is ignored and Location is ignored for values other than None. The common scenario to use No Store is may be to display error page. Most likely error page is user specific and we don’t want to show one error page generated by one user to another user.
VaryByHeader : Type string
When set, a vary response header will be written with the response. When the value of the header will change, the cached version will be invalid.
CacheProfileName : Type string
When set, determines the name of the cache profile to use. We can specify cache profile in Configuration section of ASP.NET 5 application.
Order int
The order of the filter (from IOrderedFilter
).
Cache Profile
We can maintain the Cache profile in application level and use in action or controller level. The mechanism will reduce code repetation. In this example we have created one cache profile called private cache.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.CacheProfiles.Add("PrivateCache",
new CacheProfile()
{
Duration = 60,
Location = ResponseCacheLocation.None
});
});
services.AddCaching();
}
Now, we can use the profile in controller/action level. Here is example code to implement same.
[ResponseCache(CacheProfileName = "PrivateCache")]
public ActionResult ResponseCache()
{
return View("Index");
}
In memory cache
In memory caching uses memory allocated to process for storing information. It is not distributed and scalable because the cached data is stored in server process. To configure In Memory cache, we need to add following packages in project.json file.
"Microsoft.Extensions.Caching.Memory": "1.0.0-rc1-final",
"Microsoft.Extensions.Caching.Abstractions": "1.0.0-rc1-final"
Caching in ASP.NET Core is a service that should be referenced from your application by Dependency Injection. To register the caching service and make it available within your app, add the following line to your ConfigureServices
method in Startup.cs file. Here is example code.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddCaching();
}
Get and Set value to In Memory Cache
In this example, we will learn to get and set value to In Memory cache. To get value we can use either the Get
or TryGateValue()
Function. To set the value we can use the Set()
function. Here is full code example of In Memory Cache.
public class HomeController : Controller
{
private IMemoryCache cache;
private static int data;
public HomeController(IMemoryCache cache)
{
this.cache = cache;
}
public ActionResult Index()
{
var Time = DateTime.Now.ToLocalTime().ToString() ;
this.cache.Set("Time", Time, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = (DateTime.Now.AddMinutes(1) - DateTime.Now ) });
ViewBag.Time = Time;
return View();
}
public IActionResult GetCache()
{
string Time = null;
if (this.cache.TryGetValue("Time", out Time))
{
ViewBag.Time = Time;
}
else
ViewBag.Time = DateTime.Now.ToLocalTime().ToString();
return View("Index");
}
The Index
action is catching current date time in cache and when we are calling the GetCache()
function, it checks in cache at first. If cache is present then will return from cache otherwise it will return fresh date time. The duration of Cache is one minute because in time of cache set we have specified the value.
this.cache.Set("Time", Time, new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = (DateTime.Now.AddMinutes(1) - DateTime.Now ) });
in AbsoluteExpirationRelativeToNow
property. The other way to set the expire value as shown below.
_this.cache.Set("key", "Value", new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(1)));
Setting cache priority
By default, an instance of MemoryCache
will automatically manage the items stored, removing entries when necessary in response to memory pressure in the app. You can influence the way cache entries are managed by setting their CacheItemPriority
when adding the item to the cache. For example, if you have an item you want to keep in the cache unless you explicitly remove it, you can use the NeverRemove
priority option.
new MemoryCacheEntryOptions()
.SetPriority(CacheItemPriority.NeverRemove))
If you want to explicitly remove cache entry, you can call remove()
function like this. cache.Remove("Key");
Conclusion
Response cache allows the client to cache response various cache levels and in Memory cache allows to cache in process memory. However, they are not distributed and scalable in nature. ASP.NET 5 supports Distributed cache as well where we can store cache data in SQL or Redis clustered.