Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cache.SetMaxAge not working under IIS, works fine under VS Dev Srv

I'm trying to add a "max-age" header to my response. It works fine on my Visual Studio Development Server, but as soon as I move the app to IIS (tried both IIS express locally and IIS on the server) - the header disappears.

My code:

Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0, 0));

VS Dev server response (all works just fine):

HTTP/1.1 200 OK
Server: ASP.NET Development Server/10.0.0.0
Date: Fri, 07 Jan 2011 14:55:04 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: public, max-age=86400

IIS7 Response

HTTP/1.1 200 OK
Server: Microsoft-IIS/7.5
Date: Fri, 07 Jan 2011 15:00:54 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: public

PS. It's an ASHX-handler, if it matters...

like image 828
Alex from Jitbit Avatar asked Jan 07 '11 14:01

Alex from Jitbit


2 Answers

UPDATE: 2011-03-14 The fix is ensure you call SetSlidingExpiration(true)

context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(5));
context.Response.ContentType = "image/jpeg";
context.Response.Cache.SetSlidingExpiration(true);

If you remove the OutputCache module you will get the desired result. I see this as a bug.

So, in your web.config you would do the following:

  <system.webServer>
      <modules runAllManagedModulesForAllRequests="true">
          <remove name="OutputCache"/>
      </modules>
  </system.webServer>

ADDED: So, there's additional information.

  1. Using MVC's OutputCacheAttribute apparently doesn't have this issue
  2. Under the same MVC application, without removing "OutputCache" from the modules, a direct implementation if IHttpHandler or an ActionResult results in the s-maxage being stripped

The following strips the s-maxage

         public void ProcessRequest(HttpContext context)
    {
        using (var image = ImageUtil.RenderImage("called from IHttpHandler direct", 5, DateTime.Now))
        {
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetMaxAge(TimeSpan.FromMinutes(5));
            context.Response.ContentType = "image/jpeg";
            image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
        }            
    }

The following strips the s-maxage

          public ActionResult Image2()
    {
        MemoryStream oStream = new MemoryStream();

        using (Bitmap obmp = ImageUtil.RenderImage("Respone.Cache.Setxx calls", 5, DateTime.Now))
        {
            obmp.Save(oStream, ImageFormat.Jpeg);
            oStream.Position = 0;
            Response.Cache.SetCacheability(HttpCacheability.Public);
            Response.Cache.SetMaxAge(TimeSpan.FromMinutes(5));
            return new FileStreamResult(oStream, "image/jpeg");
        }
    }

This does NOT - go figure...

    [OutputCache(Location = OutputCacheLocation.Any, Duration = 300)]
    public ActionResult Image1()
    {
        MemoryStream oStream = new MemoryStream();

        using (Bitmap obmp = ImageUtil.RenderImage("called with OutputCacheAttribute", 5, DateTime.Now))
        {
            obmp.Save(oStream, ImageFormat.Jpeg);
            oStream.Position = 0;
            return new FileStreamResult(oStream, "image/jpeg");
        }
    }
like image 83
Shawn Cicoria Avatar answered Oct 23 '22 08:10

Shawn Cicoria


Solution:

in web.config:

    <staticContent>
      <clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00"/>
    </staticContent>

and en IIS PC:

With cmd go to c:\windows\system32\inetsrv.

Then execute:

appcmd unlock config /section:staticContent
like image 24
Anton Avatar answered Oct 23 '22 09:10

Anton