问题
I have implemented my own custom Authorization Attribute in MVC 4 by inheriting from AuthorizeAttribute
class. I also have a custom ActionFilterAttribute
. These both work fine however the problem lies in ordering them. I need the custom Action Filter to run before the custom Authorize Filter.
I have tried using the Order
property for the attributes but as i understand it, Authorize Filters will always run before Action Filters.
Does anyone know how to force the Action Filter to execute before the Authorize Filter??
回答1:
When you take a look at the source code (available at http://aspnetwebstack.codeplex.com/) you see that this is not possible with the standard Filter classes. IAuthorizationFilter
implementations are always executed before IActionFilter
implementations. That's because action filters will not run when authorization filters return a result.
To solve this you can create your own ControllerActionInvoker
descendant class and override the InvokeAction
method:
public class MyControllerActionInvoker : ControllerActionInvoker
{
public override bool InvokeAction(ControllerContext controllerContext, string actionName)
{
// Your initialization code here
try
{
return base.InvokeAction(controllerContext, actionName);
}
finally
{
// Your finalization code here
}
}
}
You need to inject your custom MyControllerActionInvoker
class into your controllers in a custom ControllerFactory
class:
public class MyControllerFactory : DefaultControllerFactory
{
private readonly MyControllerActionInvoker actionInvoker = new MyControllerActionInvoker();
/// <summary>
/// Retrieves the controller instance for the specified request context and controller type.
/// </summary>
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
var controllerInstance = base.GetControllerInstance(requestContext, controllerType);
if (controllerInstance != null)
{
var typedController = controllerInstance as Controller;
if (typedController != null)
{
typedController.ActionInvoker = this.actionInvoker;
}
}
return controllerInstance;
}
}
And of course you now have to register your own MyControllerFactory
with the MVC framework. You should do this where you're also registering your routes:
var controllerFactory = new MyControllerFactory();
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
This implementation works fine here.
来源:https://stackoverflow.com/questions/11496561/how-to-execute-action-filter-before-authorization-filter-mvc-4