Atlas 7: Caching web service response on browser and save bandwidth significantly

Browser can cache images, javascripts, css files on users hard drive and it can also cache Xml Http calls if the call is a Http Get. The cache is based on Url. If it's the same Url and it's cached on the computer then the response is loaded from cache, not from the server when it is requested again. Basically, browser can cache any Http Get call and return cached data based on Url. If you make a Xml Http call as Http GET and server returns some special header which informs the browser to cache the response; on future calls, the response will be immediately returned from the cache and thus save the delay of network roundtrip and download time.

At Pageflakes, we cache user's state so that when user visits again the following day, user gets a cached page which loads instantly from browser cache, not from the server. Thus second time load becomes very fast. We also cache several small parts of the page which appears on users action. When user does the same action again, a cached result is loaded immediately from local cache and thus saves the network roundtrip time. User gets a fast loading site and a very responsive site. The perceived speed increases dramatically.

The idea is to make Http Get calls while making Atlas web service calls and return some specific Http Response headers which tells the browser to cache the response for some specific duration. If you return "Expires" header during the response, browser will cache the Xml Http response. There are 2 headers that you need to return with response which will instruct browser to cache the response:

HTTP/ 1.1 200 OK Expires: Fri , 1 Jan 2030 Cache-Control: public

This will instruct browser to cache the response till Jan 2030. As long as you make the same Xml Http call with the same parameters, you will get cached response from the computer and no call will go to the server. There are more advanced ways to get further control over response caching. For example, here is a header which will instruct browser to cache for 60 seconds but do contact server and get a fresh response after 60 seconds. It will also prevent proxies from returning cached response when browser local cache expires after 60 seconds.

HTTP/ 1.1 200 OK Cache-Control: private , must-revalidate , proxy-revalidate , max-age = 60

Let's try to produce such response headers from ASP.NET web service call:

This will result in the following response headers:

Expires header is set properly. But the problem is with Cache-Control. It is showing "max-age" is set to zero which will prevent browser from doing any kind of caching. If you seriously want to prevent caching, you should emit such cache-control header. Looks like exactly the opposite thing happened.

There's a bug in ASP.NET 2.0 that you cannot change "max-age" header. As max-age is set to zero, ASP.NET 2.0 sets Cache-Control to private because max-age = 0 means no cache needed. So, there's no way you can make ASP.NET 2.0 return proper headers which caches the response.

Time for a hack. After decompiling the code of HttpCachePolicy class (Context.Response.Cache object's class), I found the following code:

Somehow, this._maxAge is getting set to zero and the check: "if (!this._isMaxAgeSet || (delta < this._maxAge))" is preventing it from getting set to a bigger value. Due to this problem, we need to bypass the SetMaxAge function and set the value of the _maxAge field directly using Reflection.

This will return the following headers:

Now max-age is set to 60 and thus browser will cache the response for 60 seconds. If you make the same call again within 60 seconds, it will return the same response. Here's a test output which shows the date time returned from the server:

The client side code is like this:

function cachedHttpGet() { WebService.CachedGet( { useGetMethod: true , onMethodComplete: function (result) { debug.dump(result); } } ); }

Here you see, the response is cached for 60 seconds and after the time elapsed, there was a server call made and new date was returned. That response was again cached for 60 seconds.

Published Sat, Sep 23 2006 18:04 by omar
Filed under: