I’m working on a web app in ASP.NET 2.0 that involves serving images via a resource handler (.ashx). I’ve just implemented handling cache headers and conditional GET requests, so that I don’t have to serve all the images for every request. But I’m not sure I’m completely understanding what’s happening with the browser’s cache.
Images are fetched via urls like http://www.mysite.com/image.ashx?imageID=3. My code in the handler looks something like this:
int imageID = -1;
try
{
imageID = Int32.Parse(context.Request["imageID"]);
}
catch (Exception) {}
MyImageClass image = DataLayer.GetImage(imageID);
if (image != null)
{
DateTime requestedDate = DateTime.MinValue;
if (context.Request.Headers["If-Modified-Since"] != null)
{
requestedDate = DateTime.Parse(context.Request.Headers["If-Modified-Since"])
.ToLocalTime();
}
if (requestedDate < image.ModifiedDate)
{
context.Response.AddHeader("content-type", image.ContentType);
context.Response.CacheControl = HttpCacheability.Private.ToString();
context.Response.Cache.SetLastModified(image.ModifiedDate.ToUniversalTime());
context.Response.Cache.SetMaxAge(TimeSpan.FromDays(1));
//write image to output stream
}
else
{
context.Response.StatusDescription = "Not Modified";
context.Response.StatusCode = 304;
}
}
This is what the response header looks like the first time an image is requested:
HTTP/1.1 200 OK
Cache-Control: private, max-age=86400
Content-Length: 1048576
Content-Type: image/jpeg
Expires: Sat, 28 Jan 2012 17:17:11 GMT
Last-Modified: Fri, 27 Jan 2012 16:50:27 GMT
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Fri, 27 Jan 2012 17:17:10 GMT
And this is a response to a subsequent request:
HTTP/1.1 304 Not Modified
Cache-Control: private
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Fri, 27 Jan 2012 17:17:30 GMT
Connection: close
Watching the requests in Fiddler, I’m noticing that the browser (Firefox 9) always makes a conditional GET request for the image after the first request. It gets the 304 Not Modified response and pulls the image from cache, which is great. But isn’t there a way to make it always pull from the cache, without even asking the server, until after the header’s max-age (or expiry date) is past? I’ve tried using context.Response.Cache.SetExpires() with a future date, and the browser still makes the conditional GET request.
When you press F5 or Reload, Firefox will always send conditional requests.
If you navigate to the page normally (eg, clicking a link or using the address bar), it will go straight to the cache.