Avoiding "connection: close" when returning a 304 (Not Modified) status code in ASP.NET (Part 1)
First, a short introduction to the 304 status code and how to use it in ASP.NET.
Let’s say you have an ASP.NET page that returns data which can be cached on the client. Let’s also assume that this data doesn’t change often and you want the client to “ask” whether the data has changed before you return it. How do you that on the web? You use a few standard HTTP headers and the 304 response code.
Let’s start with a very useless but simple example. Suppose we have an HTTP handler that returns the current time updated to the minute:
public void ProcessRequest(HttpContext context) { DateTime now = DateTime.Now; DateTime time = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0); context.Response.Write(time.ToString("HH:mm")); }
We just grab the current time, turn it into a DateTime without seconds and send it to the response stream.
Now, Since we only provide the time up to the second, It seems reasonable to tell the client to cache this result and don’t bother us again at least for another.. well for another minute. How do we do that? We set the Expires header:
public void ProcessRequest(HttpContext context) { ...
context.Response.Cache. SetExpires(time.AddMinutes(1)); context.Response.Write(time.ToString("HH:mm")); }
This basically tell the client not to bother contacting the server for another minute since there won’t be any changes anyway.
But what will a user do if he’s sure that a minute already passed but the page still displays the old time? He’ll click the Refresh button. The browser will now send the request again and our handler will return the time again.
Since it takes a lot of resources to process that request, we would like our client to send the server something like “I have a cached version of this page from date XY. Do you have a newer version?”. To do that, our client has to know when was this resource last updated. If you’re retuning files, you can use the last modification date of the file. If you’re reading records from a database and you have a “MODIFICATION_DATE” column, you can use that. In our case, we simply return the time itself:
public void ProcessRequest(HttpContext context) { ...
context.Response.Cache.SetLastModified(time); context.Response.Cache. SetExpires(time.AddMinutes(1)); context.Response.Write(time.ToString("HH:mm")); }
Now, when the user hits the refresh button, the browser will send an HTTP request with the following header:
If-Modified-Since: Sun, 09 Sep 2007 18:19:00 GMT
All we have to do now, is check whether the client passed this header, check if our data has changed since that time and if nothing has changed, send a 304 response code without sending the data itself:
NameValueCollection headers = context.Request.Headers; DateTime ifMod; if (DateTime.TryParse(headers["If-Modified-Since"], out ifMod)) { TimeSpan delta = DateTime.Now - ifMod; if (delta < TimeSpan.FromMinutes(1)) { //nothing has changed, return 304 context.Response.StatusCode = 304; return; } }
Great, so what does all this have to do with this post title? This, and more in the next episode of..
One Response to “Avoiding "connection: close" when returning a 304 (Not Modified) status code in ASP.NET (Part 1)”
pistro
June 23rd, 2009
I am having problems with jpeg files exported from Lightroom 2.2 http://www.ebook-search-queen.com/ebook/ligh/lightroom-2.2.all.html . I dont think ImageGetExifMetadata working properly for LR images. I can see the all exif information with a different programs. One of the errors:”Element Focal Plane Y Resolution is undefined in a CFML structure referenced as part of an expression. “. “Element Focal Plane Y Resolution” is there but CF can’t read it. I have tried all sorts with no luck.On the other hand it works for non LR jpg images. Any ideas?