views:

510

answers:

2

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?

A: 

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.

Peter J
You gave in????? ;) Can you give a synopsis of your final reasoning?
Alex
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
Need some clarification here: http://stackoverflow.com/questions/1441799/authorization-and-asp-net-mvc-caching
Alex
+2  A: 

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