Introduce the Problem
We have successfully configured the browser cache to return a saved response if the server indicates 304 Not Modified
. Here is the config:
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add
name="TransparentClient"
location="Client"
duration="0" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
The web.config is perfect and sets Cache-control:private, max-age=0
so that:
The problem is that our MVC.NET Actions always respond 200 and never 304.
The Problem
How do we configure output caching to return a 304 Not Modified when an ActionResult hasn't changed?
The roll-our-own will probably require an Action Filter with ETag or Last-Modified.
Screen Shots
Here is a Fiddler screenshot showing the lack of a 304.
Search and Research
ASP.NET MVC : how do I return 304 "Not Modified" status? mentions returning a 304 from within the Action. That does not provide a way to make the OutputCache accurately respond with a 304.
Working with the Output Cache and other Action Filters shows how to override the OnResultExecuted, which will allow adding/removing headers.
The following is working for us.
Set Cache-Control:private,max-age-0
to enable caching and force re-validation.
<system.web>
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="TransparentClient" duration="0" location="Client" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
Respond with 304 if the response is not modified.
[MyOutputCache(CacheProfile="TransparentClient")]
public ActionResult ValidateMe()
{
// check whether the response is modified
// replace this with some ETag or Last-Modified comparison
bool isModified = DateTime.Now.Second < 30;
if (isModified)
{
return View();
}
else
{
return new HttpStatusCodeResult(304, "Not Modified");
}
}
Remove the Cache-Control:private,max-age-0
otherwise the cache will store the status message.
public class MyOutputCache : OutputCacheAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
if (filterContext.HttpContext.Response.StatusCode == 304)
{
// do not cache the 304 response
filterContext.HttpContext.Response.CacheControl = "";
}
}
}
Fiddler shows that the cache is acting appropriately.
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