In previous versions of ASP.NET MVC, action filters were created per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.
Taken from the 'breaking changes' section of the release notes for MVC3.
The statement is clear enough to someone feeling the sting still from a recent live issue, but I've outlined a bad and good example of custom action filters below. Basically, if you find yourself needing to store state for the lifetime of a request, use the filterContext.HttpContext.Items collection.
Bad custom action filter
public class BadActionFilter : ActionFilterAttribute { private string _userState; public override void OnActionExecuting(ActionExecutingContext filterContext) { _userState = someSortOfDataUniqueToUser(); } public override void OnActionExecuted(ActionExecutedContext filterContext) { // using _userState here is a bad idea! } }
Good custom action filter
public class GoodActionFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var userState = someSortOfDataUniqueToUser(); filterContext.HttpContext.Items["userState"] = userState; } public override void OnActionExecuted(ActionExecutedContext filterContext) { var userState = filterContext.HttpContext.Items["userState"]; // using userState here is perfectly fine! } }