Cache-Control header cannot be set properly in ASP.NET 2.0 - A solution

Do you know that you cannot set Cache-Control: max-age header in ASP.NET 2.0? No matter how many combinations you try, you will always end up with "max-age=0" for sure.

I found solution to the SetMaxAge problem in HttpCachePolicy. Here's the code of the function in HttpCachePolicy (decompiled):

public void SetMaxAge(TimeSpan delta)
        {
            if (delta < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException("delta");
            }
            if (HttpCachePolicy.s_oneYear < delta)
            {
                delta = HttpCachePolicy.s_oneYear;
            }
            if (!this._isMaxAgeSet || (delta < this._maxAge))
            {
                this.Dirtied();
                this._maxAge = delta;
                this._isMaxAgeSet = true;
            }
        }

Someone is setting maxAge already to 0. So, if I assign a higher value it does not get set.

I am not sure why the "(delta < this._maxAge)" condition is necessary. If I somehow set a lower maxAge, I can never increase it!

So, I have made an HttpModule which does this:

void context_EndRequest(object sender, EventArgs e) {
 if (HttpContext.Current.Items.Contains("SetMaxAge"))
      {
            FieldInfo maxAge = HttpContext.Current.Response.Cache.GetType().GetField("_maxAge", BindingFlags.Instance | BindingFlags.NonPublic);
            maxAge.SetValue(HttpContext.Current.Response.Cache, (TimeSpan)HttpContext.Current.Items["SetMaxAge"]);

      // SetMaxAge does not work.             //HttpContext.Current.Response.Cache.SetMaxAge((TimeSpan)HttpContext.Current.Items["SetMaxAge"]);
            HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.Public);            HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddMinutes(5));            HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
      }
}

If someone sets "SetMaxAge" to a Timespan in the Context.Items, it will get set to the response and the end of the request. This ensures, no matter who does what with cache object, maxAge will definitely be set.

Although this is not a Atlas specific problem, it seems to be a problem in ASP.NET 2.0 itself.

Now I can cache AJAX call responses on the browser and prevent roundtrips.

Published Wed, Aug 2 2006 13:47 by omar
Filed under:

Comments

# re: Cache-Control header cannot be set properly in ASP.NET 2.0 - A solution

Wednesday, September 19, 2007 1:25 AM by Milan

Hi,

What abount 3.x version of frameworks? Do they have the same issue?

# re: Cache-Control header cannot be set properly in ASP.NET 2.0 - A solution

Tuesday, January 08, 2008 1:58 PM by David Stevenson

I am getting a max-age of 9999999 and TWO Cache-Control headers. the max-age of 9,999,999 seconds, or about 115 days, which conflicts with my setting of 365 days in the Expires HTTP header. I am wondering why I am getting TWO Cache-Control headers, and a max-age I didn't specify.

HTTP/1.1 200 OK

Server: Microsoft-IIS/5.0

Date: Tue, 08 Jan 2008 19:49:41 GMT

X-Powered-By: ASP.NET

Cache-Control: public, max-age=9999999

X-AspNet-Version: 2.0.50727

Cache-Control: public

Expires: Wed, 07 Jan 2009 19:49:41 GMT

Last-Modified: Thu, 28 Jul 2005 22:08:28 GMT

Content-Type: image/gif

Content-Length: 2306

resp.Cache.SetExpires(DateTime.Now.AddSeconds(365 * 24 * 60 * 60));    // Expires in one year.

               // Public - Allows the response to be cached by clients and shared (proxy) caches.

resp.Cache.SetCacheability(HttpCacheability.Public);

resp.Cache.SetValidUntilExpires(true);

FileInfo file = new FileInfo(path);

resp.Cache.SetLastModified(file.LastWriteTimeUtc);

David Stevenson

Leave a Comment

(required) 
(required) 
(optional)
(required)