This question is related to my other question.
I have an MVC application with caching disabled for all controller actions. I do this by setting cache response headers in Application_BeginRequest
:
protected void Application_BeginRequest()
{
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.Cache.SetNoStore();
}
There is single controller action for which I do want caching enabled. I have decorated this action with the OutputCache
attribute:
[OutputCache(Duration = 300, VaryByParam = "id")]
What happens now for this action? Does it get cached because of the OutputCache attribute, or is it not cached because of the response headers?
-- EDIT --
As it seems, the response headers take preference. So my question becomes: how can I enable cache for single controller actions? Overwrite the response headers again?
The two things are separate; the response cache is primarily looking at what the client sees - what they will use without hitting the server, or what modified-date they will send up to the server.
OutputCache, however, is focused at the server; the request will still happen (unlike something cached at the client), but it is possible (hopefully likely) that your method won't be called: instead, the cached version will be returned.
So: it is not cached at the client; a HTTP request is made, and (for requests within 5 minutes, for the same id
, memory permitting) the cached version is returned from the server (typically reducing IO and CPU load at the server). Make sense?
The response headers enforce the cache control. The solution was not to set response headers for controller actions that require caching. Instead of using OutputCache
, I'm now using a custom cache attribute that also sets an ISCACHED
key in the request items dictionary. The code snippet from my question was changed to this:
protected void Application_EndRequest()
{
if (HttpContext.Current.Items["ISCACHED"] == null)
{
var cache = HttpContext.Current.Response.Cache;
cache.SetCacheability(HttpCacheability.NoCache);
cache.SetNoStore();
cache.SetExpires(DateTime.Now.AddDays(-1));
}
}
I had to move this from BeginRequest
to EndRequest
, to allow actions to set the ISCACHED
request item first. If it is set, a controller already handled caching for this request, otherwise caching is disabled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With