6

I'm implementing a simple REST service with the WCF Web API and attempt to set HTTP headers in order to cache responses.

For a simple GET like this

http://localhost:49302/my/2

the response headers look like this:

Server: ASP.NET Development Server/10.0.0.0
Date: Tue, 24 Jan 2012 18:18:44 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 233
Cache-Control: max-age=120
Vary: Accept
Expires: Tue, 24 Jan 2012 18:20:44 GMT
Last-Modified: Tue, 24 Jan 2012 18:18:15 GMT
Content-Type: application/xml; charset=utf-8

The intent is that the client should cache the resource for two minutes.

However, using the WCF Web API Test Client, the behavior is inconsistent across various browsers:

  • In Firefox (9.0.1) the request is cached, and first after two minutes is a new version of the resource displayed. This behavior is as expected.
  • In Chrome (16.0.912.77 m) the cache headers aren't respected at all. A new version of the resource is being fetched for every GET request. This behavior is not expected (by me, at least).
  • In Internet Explorer (9) the behavior is the same as in Chrome.

Why doesn't Chrome and IE respect the cache headers?

Is it a bug in the WCF Web API Test Client?

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
  • 1
    WCF Web API Test Client is very new so it might have a bug. Can you test directly with the browser or write a small test page. – suing Jan 25 '12 at 03:02

2 Answers2

4

Caching is hard to get right. The fact that a browser may ignore cache directives certainly doesn't help.

According to this document IE never cached any request with a Vary header containing anything but Accept-Encoding and User-Agent

If I test this with a 15 seconds cache period and I just set the MaxAge and MustRevalidate it seems to work fine with IE9, FireFox and Chrome.

Web API HttpResponseMessage:

result = new HttpResponseMessage<Book>(book);
result.Headers.CacheControl = new CacheControlHeaderValue();
result.Headers.CacheControl.MaxAge = TimeSpan.FromSeconds(15);
result.Headers.CacheControl.MustRevalidate = true;
return result;

Response headers:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 25 Jan 2012 09:13:32 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 98
Cache-Control: must-revalidate, max-age=15
Content-Type: application/json; charset=utf-8
Connection: Close

I am not sure the MustRevalidate is really required but it is recommended to use it. See the specs here.

Maurice
  • 27,582
  • 5
  • 49
  • 62
  • That's a pretty interesting insight about browsers ignoring cache directives. However, even though I've trimmed down my headers to be very close to the ones posted here, I'm still not seeing Chrome or IE9 caching the response. – Mark Seemann Jan 26 '12 at 13:17
  • Turns out cache directives are just a hint and the browser is quite free to ignore it. Using must-revalidate is a hint to the browser to be stricter, Not sure what the different. I was testing on localhost and not using the test client but used a button on a regular HTML page with a jQuery $.getJSON() call. – Maurice Jan 26 '12 at 13:51
2

Test to replace localhost with "real domain" so the WCF Test Client or Chrome/IE doesnt have any special tricks for localhost.

DNPE
  • 63
  • 7
  • That was actually a pretty reasonable suggestion, since I hadn't thought about that, but alas it doesn't make a difference. I'm still running on my local box, though, but I've tried with both my local machine name (NETBIOS), as well as a 'fully qualified' DNS-like name. – Mark Seemann Jan 24 '12 at 21:18