Set jQuery cache option and Response headers to expire cached response

Recently I was working on an ASP.Net MVC based trading platform application using ASP.Net MVC4 framework. I ran into a very interesting bug. On one of the pages had a data table that was refreshing data using asynchronous ajax form using Ajax.BeginForm. The table had some action links that were triggering manual async requests to update data. The issue I saw was that response for these ajax requests was rendering updated data from server. Each request was rendering old data. And in one case it managed to render data from 2 days ago.

I started debugging process. First I looked at Model data for the view. The data was old as well. That means the server was not serving latest data for ajax request. Then I put break point on server side. The request was making it to server controller. It was generating correct set of data and was setting it correctly as well. But the rendered view not reflecting latest data.

It turned out that problem was being caused by cached response. MVC framework was generating correct HTML but when response object was sent to client, client ended up using cached view. MVC framework uses jQuery ajax function from their async implementation in jquery.unobtrusive-ajax.js file. The implementation uses default settings for ajax. The default behavior of .ajax method is to use cached response. jQuery documentation states that if you set cache option to false then cached response will not be used. It seems that that setting is not sufficient in itself.

Set cache expiration from server response

A web client will not cache response if response sets appropriate cache headers and tell the client that response is not to be cached or can be cached for certain duration only. This means you will need to add some implementation to set these headers. I have implemented a small extension method in my MVC application that accomplishes this.

public static class ApiExtensions
{
  public static void ExpireImmediately(this HttpResponse response)
  {
    response.Cache.SetExpires(DateTime.Now.AddDays(-1));
    response.Cache.SetMaxAge(TimeSpan.FromMilliseconds(0));
    response.Cache.SetCacheability(HttpCacheability.NoCache);
    response.Expires = -1;
    response.ExpiresAbsolute = DateTime.Now.AddDays(-1);
  }
}
    

The reason I have set all these headers is that some older clients only understand certain header types and some do not. To cover all cases I decided to set whatever options I could set.

Set .ajax method cache option

You will also need to set cache option to false in your jQuery ajax method request. Following code snippet shows how I did it in my application.

$.ajax({
     url: "http://localhost/ByteBlocks/Api/StocksService.asmx/GetMostActiveStocks",
     type: "POST",
     data:"{'stockExchange':'NYSE'}",
     contentType: "application/json; charset=utf-8",
     dataType: "json",
     crossDomain: false,
     cache: false,
     timeout:10000,
     headers: { 'Authorization': basicAuth },
     success: function (data, status, xhr) {
     },
     error: function (xhr, status, err) {
     }
    });
    

Bottom line is, if you ever run into a situation where you see that response is not fresh start by looking at response headers using tools like Fiddler, FireBug etc. And hopefully it will provide enough clues to put a fix for issue.

comments powered by Disqus

Search

Social

Weather

9.2 °C / 48.6 °F

weather conditions Clouds

Monthly Posts

Blog Tags