views:

40

answers:

1

I have a dynamically generated CSS file. It's fairly large, and has different content for different browsers. It changes very rarely.

So at the top of the .aspx page I have:

<%@ OutputCache Duration="86400" 
                Location="ServerAndClient" 
                VaryByParam="none" 
                VaryByCustom="browser" %>

I have a similar directive against MVC actions that generate dynamic images:

[OutputCache(Duration = 86400, 
             VaryByParam = "none", 
             Location = OutputCacheLocation.ServerAndClient)] 

This should result in the file being cached on the server and the client (but not intermediate proxies) for a day.

The response headers appear to be correct:

HTTP/1.1 200 OK
Cache-Control: private, max-age=83831
Content-Type: text/css; charset=utf-8
Expires: Wed, 09 Jun 2010 08:52:45 GMT
Last-Modified: Tue, 08 Jun 2010 08:52:45 GMT
Vary: *
Server: Microsoft-IIS/7.0
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Tue, 08 Jun 2010 09:35:34 GMT
Content-Length: 70073

The server side caching works - further requests do not execute the code again.

However the client side caching is broken in two different ways: firstly the content is requested again on every page, despite the fact that it should be cached.

Why does the browser request the content again?

Secondly when the server is asked for the content again it returns an HTTP 200 along with the entire content. It should return an HTTP 304 Not Modified with no body - telling the browser to re-use what it has already downloaded.

How do I make sure that it returns an HTTP 304 when the content hasn't changed?

+2  A: 

1) Vary: * will cause certain browsers, such as IE, not to cache. Vary: User-Agent might work better (not sure).

2) WRT 200 vs 304: does the client send an If-* header?

Julian Reschke
Cheers - looks like that `vary:*` header was the reason IE didn't cache (yet another IE bug!) fixed by adding `<system.web><caching><outputCache omitVaryStar="true" /></caching></system.web>` to the web.config
Keith
The client doesn't send an `If-None-Match` request header though - probably because there's no `ETag` in the response.
Keith
It could send an If-Modified-Since, but of course supplying an ETag is preferable anyway.
Julian Reschke
This looks like a bug in ASP.Net - if I remove `VaryByCustom="browser"` the 304 request works correctly with `If-Modified-Since`. I've changed it to `VaryByHeader="User-Agent"` and that works as expected.
Keith