6

I'm developing an ASP.NET MVC application. Most of the controller actions are not supposed to be cached. Because of this I output no-cache headers in Application_BeginRequest:

    protected void Application_BeginRequest()
    {
        HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
        HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        HttpContext.Current.Response.Cache.SetNoStore();
    }

The application is running on IIS7 with modules config setting runAllManagedModulesForAllRequests="true". This means that all static files pass through the request pipeline as well (and get caching disabled).

What is the best way to keep caching enabled for these static files? Do I have to check on extension before setting the response cache headers in Application_BeginRequest or is there an easier way (like bypassing the request pipeline for static files altogether)?

dove
  • 20,469
  • 14
  • 82
  • 108
Carvellis
  • 3,992
  • 2
  • 34
  • 66

2 Answers2

4

Assuming that you can't avoid using runAllManagedModulesForAllRequests="true" as in Hector's link, you could check the type of the request handler and only set the caching headers if the request is being handled by MVC.

protected void Application_PreRequestHandlerExecute()
{
    if ( HttpContext.Current.CurrentHandler is MvcHandler )
    {
        HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        HttpContext.Current.Response.Cache.SetValidUntilExpires(false);
        HttpContext.Current.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        HttpContext.Current.Response.Cache.SetNoStore();
    }
}

Note that I've moved the code into Application_PreRequestHandlerExecute because the handler hasn't yet been chosen in BeginRequest, so HttpContext.Current.CurrentHandler is null.

stevemegson
  • 11,843
  • 2
  • 38
  • 43
  • This works nicely. It also allows you to set custom cache control for static files in the else statement. – Carvellis Nov 03 '10 at 12:30
3

You could have a Caching filter attribute that applies this to all your actions (either through a base controller or explicitly on each controller or action). This would not the apply to you static files.

Possible [CacheFilter]:

using System;
using System.Web;
using System.Web.Mvc;

    public class CacheFilterAttribute : ActionFilterAttribute
    {

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;

            cache.SetExpires(DateTime.UtcNow.AddDays(-1));
            cache.SetValidUntilExpires(false);
            cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            cache.SetCacheability(HttpCacheability.NoCache);
            cache.SetNoStore();
        }
    }

As an aside could you even deliver your static files from a different domain, like SO do with sstatic.net, which would eliminate your problem as a side effect.

dove
  • 20,469
  • 14
  • 82
  • 108