Can I return an action result from an action filter?
I just found the solution after searching a bit in the ASP.NET MVC source code:
It can't be done with an action filter because that is called before and after the action method is called, but it does not actually wrap the action method call.
However, it can be done with a custom ActionMethodInvoker:
public class CustomActionInvoker : ControllerActionInvoker
{
protected override ActionResult InvokeActionMethod(
ControllerContext controllerContext,
ActionDescriptor actionDescriptor,
System.Collections.Generic.IDictionary<string, object> parameters)
{
try
{
//invoke the action method as usual
return base.InvokeActionMethod(controllerContext, actionDescriptor, parameters);
}
catch(ValidationException e)
{
//if some validation exception occurred (in my case in the business layer)
//mark the modelstate as not valid and run the same action method again
//so that it can return the proper view with validation errors.
controllerContext.Controller.ViewData.ModelState.AddModelError("",e.Message);
return base.InvokeActionMethod(controllerContext, actionDescriptor, parameters);
}
}
}
And then, on the controller:
protected override IActionInvoker CreateActionInvoker()
{
return new CustomActionInvoker();
}
You can obviously set the action result in action filter. But if you are using the ActionExecuting (filterContext.Result)to set the action result then your controller code will not be invoked. I think instead of ActionFilter, if the extra validation logic is tied with the model, a better solution would to use a Custom Model binder.
Hope that helps.