How to skip action execution from an ActionFilter?
Is it possible to skip the whole action method execution and return a specific ActionResult
when a certain condition is met in OnActionExecuting
?
You can use filterContext.Result for this. It should look like this:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Check your condition here
if (true)
{
//Create your result
filterContext.Result = new EmptyResult();
}
else
base.OnActionExecuting(filterContext);
}
See my download sample and MSDN article Filtering in ASP.NET MVC.
You can cancel filter execution in the OnActionExecuting
and OnResultExecuting
methods by setting the Result
property to a non-null value.
Any pending OnActionExecuted
and OnActionExecuting
filters will not be invoked and the invoker will not call the OnActionExecuted
method for the cancelled filter or for pending filters.
The OnActionExecuted
filter for previously run filters will run. All of the OnResultExecutingand
OnResultExecuted
filters will run.
The following code from the sample shows how to return a specific ActionResult
when a certain condition is met in OnActionExecuting
:
if (filterContext.RouteData.Values.ContainsValue("Cancel"))
{
filterContext.Result = new RedirectResult("~/Home/Index");
Trace.WriteLine(" Redirecting from Simple filter to /Home/Index");
}
If anyone is extending ActionFilterAttribute
in MVC 5 API, then you must be getting HttpActionContext
instead of ActionExecutingContext
as the type of parameter. In that case, simply set httpActionContext.Response
to new HttpResponseMessage
and you are good to go.
I was making a validation filter and here is how it looks like:
/// <summary>
/// Occurs before the action method is invoked.
/// This will validate the request
/// </summary>
/// <param name="actionContext">The http action context.</param>
public override void OnActionExecuting(HttpActionContext actionContext)
{
ApiController ctrl = (actionContext.ControllerContext.Controller as ApiController);
if (!ctrl.ModelState.IsValid)
{
var s = ctrl.ModelState.Select(t => new { Field = t.Key, Errors = t.Value.Errors.Select(e => e.ErrorMessage) });
actionContext.Response = new System.Net.Http.HttpResponseMessage()
{
Content = new StringContent(JsonConvert.SerializeObject(s)),
ReasonPhrase = "Validation error",
StatusCode = (System.Net.HttpStatusCode)422
};
}
}
You can use the following code here.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
...
if (needToRedirect) //your condition here
{
...
filterContext.Result = new RedirectToAction(string action, string controller)
return;
}
...
}
RedirectToAction will redirect you the specific action based on the condition.