We have recently upgraded from mvc2 to mvc3 and one of our Custom Authorization Filters (which sit on ActionResult methods) seem to be constructed once, but executed multiple times. We know this as the Filter contains a list of errors (which is newed up in the constructor) and the errors are added to on the AuthorizeCore.
The Custom Filter is used to check a users access rights to a particular action method (and their level is stored in the Session)
Some code:
public class SecurityAttribute : AuthorizeAttribute
{
public int MinAccessLevel = 1;
public string UserRole = String.Empty;
private List<string> _errors;
public SecurityAttribute()
{
_errors = new List<string>();
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (WebSession.AccessLevel < MinAccessLevel)
_errors.Add("Your access level(" + WebSession.AccessLevel + ") must be " + MinAccessLevel + " or higher");
if (!String.IsNullOrEmpty(UserRole) && WebSession.UserRole != UserRole)
_errors.Add("Your User Role must be " + UserRole);
if (_errors.Any())
{
var viewResult = new ViewResult() { ViewName = "SecurityError"};
viewResult.ViewData.Model = new SecurityErrorViewModel(){Errors = _errors};
filterContext.Result = viewResult;
}
}
}
This would be used like the below:
[HttpPost, Security(MinAccessLevel = 4)]
public ActionResult Complete(int id, string userid){}
The output on the view (at random intervals) appears like so (in a bulleted list)
This issue only occurred once we upgraded to mvc3, so am looking for any clues as to why this might have happened, or appropriate fix. I have read various SO posts regarding Sessionless State controllers and the like, but this doesnt seem to fit the scenario we are facing
Thanks, Mark
As per the MVC 3 release notes:
In previous versions of ASP.NET MVC, action filters were created on a per request basis 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.
So you should not store the errors within the action filter. Either new up the list directly in the OnAuthorization
method or if you need access to them elsewhere you could store them in HttpContext.Items or Session.