MVC *always* returns status code 200 when a max age is set while it can return with 304

By ramon
June 15, 2011
0

Take a look at the following mvc csharp code:

	Response.AddFileDependency(filename)
	Response.Cache.SetETagFromFileDependencies();
	Response.Cache.SetCacheability(HttpCacheability.Public);
	Response.Cache.SetMaxAge(TimeSpan.FromHours(1));
	return File(filename, "video/mp4")

My intension of this was. Please cache this file for one hour (SetMaxAge) and then check if the file is still valid (SetEtagFromFileDependancy) and if it is then cache it again for one hour.

However, it turns out that MVC thinks different :-). When the item is expired MVC returns status code 200 even though the clients submits a matching If-None-Match header. In such cases the webserver is allowed to respond with 304 and update the item with new information passed in the response header.

It could be that I have forgotten something in the code above but the following is the workaround I created for this situation. It needs a custom etag to use so you cannot make use of SetETagFromFileDependencies. The method basically does a Etag comparison and responds with a 304 if they match. If they do not match the method returns null but has set the above mentioned headers.

	ActionResult EtagFix(string etagResponse, HttpCacheability cachability, TimeSpan maxAge)
	{
		var cache = Response.Cache;
		cache.SetETag(etagResponse);
		cache.SetCacheability(cachability);
		cache.SetMaxAge(maxAge);

		if (!etagResponse.Equals(Request.Headers["If-None-Match"])) return null;

		Response.StatusCode = 304;
		Response.StatusDescription = "Not Modified";
		return new EmptyResult();
	}

This method should be pasted as a method in your controller and then it should just work. The reason that I return null is that you can do the following nifty trick:

	return EtagFix("EtagValue", HttpCacheability.Public, TimeSpan.FromHours(1)) ?? File(Server.MapPath("~/Content/mylargefile.dat");

The reason that this is cool is that “File(Server.MapPath(“~/Content/mylargefile.dat”)” will ONLY be called with EtagFix returns null. This avoids ‘expensive’ action result implementations to be created and do work that they do not have to do.

Comments: 0

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Recent Posts
  • Recent Comments
  • Archives
  • Categories
  • Meta