5

According to various articles (e.g. here and here) attribute results on ASP.NET MVC Actions may be cached and not executed again when a controller action is called.

That behavior is not desired in my case (e.g. I have an authorization system based on my own attributes and IPs, role checks that need to execute every time, and other things).

How can I prevent ASP.NET MVC from caching my attributes/attribute execution results and guarantee that they are executed every time?

Community
  • 1
  • 1
Alex
  • 71,233
  • 79
  • 245
  • 337
  • To clarify, caching is done by ASP.NET, not ASP.NET MVC. That's part of the reason this is hard to do right inside an attribute! – Craig Stuntz Sep 18 '09 at 01:57

2 Answers2

3

Look at the source code for the AuthorizeAttribute (on Codeplex or via Reflector) to see how it goes about turning off caching for authorized pages. I refactored it into a separate method on my custom authorization attribute which derives from AuthorizeAttribute.

protected void CacheValidateHandler( HttpContext context, object data, ref HttpValidationStatus validationStatus )
{
    validationStatus = OnCacheAuthorization( new HttpContextWrapper( context ) );
}

protected void SetCachePolicy( AuthorizationContext filterContext )
{
    // ** IMPORTANT **
    // Since we're performing authorization at the action level, the authorization code runs
    // after the output caching module. In the worst case this could allow an authorized user
    // to cause the page to be cached, then an unauthorized user would later be served the
    // cached page. We work around this by telling proxies not to cache the sensitive page,
    // then we hook our custom authorization code into the caching mechanism so that we have
    // the final say on whether a page should be served from the cache.
    HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
    cachePolicy.SetProxyMaxAge( new TimeSpan( 0 ) );
    cachePolicy.AddValidationCallback( CacheValidateHandler, null /* data */);
}
tvanfosson
  • 490,224
  • 93
  • 683
  • 780
1

I just finished a spirited discussion with Craig Stuntz (the author of the first article you listed).

I ended up using an AuthorizeAttribute with AuthorizeCore to guarantee that authorization is called even in the event the page is cached.

Community
  • 1
  • 1
Peter J
  • 55,560
  • 7
  • 36
  • 45
  • My middle solution was to simply disable all caching in the Response during OnActionExecuted. It did seem a little ham-fisted, when AuthorizeCore should do the same thing for me. – Peter J Sep 17 '09 at 22:14
  • Need some clarification here: http://stackoverflow.com/questions/1441799/authorization-and-asp-net-mvc-caching – Alex Sep 17 '09 at 23:20