In my application (ASP.NET MVC 3) I have a BaseController class that all my Controllers inherit and in that BaseController I have overridden the OnActionExecuting method to check to ensure a Session variable is populated as I need access to that in all other action methods in the application. I also have a custom Authorize attribute that I have defined that extends the AuthorizeAttributeClass. In that attribute I override OnAuthorization to check the same Session variable I am loading in the BaseController OnActionExecuting method to see if the user should be permitted to continue.
BaseController
public class BaseController : Controller
{
private ISessionUserService sessionUserService;
public BaseController(ISessionUserService sessionUserService)
{
this.sessionUserService = sessionUserService;
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
if (User != null && User.Identity.IsAuthenticated && this.sessionUserService.Current == null)
{
this.sessionUserService.Start(accountID, User.Identity.Name);
// If we weren't successful in reloading the SessionUser
// variable, redirect the user to the Sign In view
if (this.sessionUserService.Current == null)
{
filterContext.Result = new RedirectResult(Url.Action("SignIn", "Access", new { area = string.Empty }));
return;
}
}
}
}
Custom Authorize Attribute
public class AuthorizeByPermission : AuthorizeAttribute
{
public Permission[] Permissions { get; set; }
public AuthorizeByPermission(params Permission[] permissions)
{
this.Permissions = permissions;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
SessionUser sessionUser = filterContext.HttpContext.Session.Get<SessionUser>();
if (sessionUser.HasPermission(Permissions))
return;
filterContext.Result = new HttpUnauthorizedResult();
}
}
The problem is that the BaseController OnActionExecuting method is firing AFTER the OnAuthorization method in my AuthorizeByPermission attribute and I need it to be the other way arround as the BaseController needs to popualte the Session variable if it isn't there before the authorize attribute attempts to access it.
Basically I need to find a way to have a base class method or a global filter that can be registered to occur before the OnAuthorization method fires. Any ideas on how to do this?
I have tried registering a GlobalFilter to load the session variable and set its Order property to be lower than the AuthorizeByPermission attribute but that didn't seem to work either.
I have also tried overriding the Execute method in the BaseController and that actually fired before the custom authorization attribute but the problem was that I didn't have access to the filterContext which allowed me to redirect the user to the SignIn page if we couldn't load the session variable.
As per bmosh's comment I tried turning my BaseController OnActionExecuting method into a separate filter and decorate the BaseController with that attribute with a lower Order number than the AuthorizeByPermission attribute but it still didn't work.
[FilterIWantToFireFirst(Order = 1)]
public class BaseController : Controller
{
}
public class AnotherController : BaseController
{
[AuthorizeByPermission(Permission.Add, Order = 2)]
public ActionResult SomeActionMethod()
{
}
}
Even with the above setup, the AuthorizeByPermission attribute is fired first.
Any ideas?
You could try overriding OnAuthorization instead of OnActionExecuting in your base controller.