How to skip action execution from an ActionFilter?
Asked Answered
S

5

47

Is it possible to skip the whole action method execution and return a specific ActionResult when a certain condition is met in OnActionExecuting?

Screech answered 23/3, 2012 at 9:59 Comment(0)
B
42

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);
}
Beer answered 23/3, 2012 at 11:21 Comment(2)
Why do you skip base.OnActionExecuting when your condition is true? In my case I need that to run before I can set the Result.Bonine
@Bonine that's just an example, the condition ay vary depending on your requirement.Ungotten
T
37

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 OnResultExecuting and 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");
}
Travax answered 23/3, 2012 at 16:29 Comment(2)
It should be noted that if you have more than one filter and the order of the filters matters you should specify the "Order" parameter when registering your filter so you can control the execution order as Rick has outlined in his details about how the Result filterContext.Result property behaves.Zincograph
Good point Nick - but see my section Filter Order - the order property only applies to filters in the same class. Auth always run first, exception, last.Travax
D
4

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
            };
        }
    }
Dowable answered 23/11, 2018 at 13:56 Comment(0)
D
2

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.

Downcomer answered 13/5, 2014 at 6:41 Comment(2)
RedirectToAction is a method (at least in MVC5) so you can't new() it.Incrustation
A worthless answer added long after the original (and correct) answers, and it's wrong as filterContext.Result must be a sub class of ActionResult. How this ever got up-voted is a mystery.Cisterna
D
0

I archived this as follows:

public void OnActionExecuting(ActionExecutingContext filterContext)
{
   if (!condition)
   {
      filterContext.Result = new RedirectToRouteResult(
      new RouteValueDictionary{ { "controller", "YourController" },
                                { "action", "YourAction" }
                              });
   }
}

This will redirect you to the given action. Worked with MVC 4.

Dalessandro answered 22/9, 2022 at 15:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.