How do I get certain code to execute before every single controller action in ASP.NET MVC 2?
Asked Answered
C

2

39

I want to check some things about the state of the session, the user agent, etc, and possibly take action and return a special view BEFORE a controller method gets a chance to execute. For example:

Most common:
User requests Home/Index
System checks to make sure x != 0.
x does not equal zero, so the Home/Index controller executes like normal.

But, sometimes:
User requests Home/Index
System checks to make sure x != 0.
x DOES equal zero. The user must be notified and the requested controller action cannot be allowed to execute.

I think this involves the use of ActionFilters. But I have read about them and I don't understand if I can preempt the controller method and return a view before it executes. I am sure I could execute code before the controller method runs, but how do I keep it from running in some instances and return a custom view, or direct to a different controller method?

Update: I implemented RM's solution. This is what I did:

public class MyAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (myValue == wrongValue)
        {
            filterContext.Result = new ViewResult{ViewName = "Notice"};
        }
        base.OnActionExecuting(filterContext);
    }
}

Now, when myValue is wrong, those users get the Notice view and the requested controller is never executed. To make this work I applied it to a ControllerBase that all my Controllers inherit from.

Cowberry answered 16/4, 2010 at 2:48 Comment(1)
Hey chris. Let me know how did you go about it?Marcellemarcellina
V
49

All depends what exactly you want to do, and how. Three options below:


You can use route constraints for this. They are executed when evaluating the route to match to.

routes.MapRoute(
    "HomeWithConstraint",
    "Home/{action}",
    new {controller="Home", action="index"},
    new { x = new MyCustomRouteConstraint () }
);

// without constraint, i.e. if above didnt pass
routes.MapRoute(
    "HomeWithConstraint",
    "Home/{action}",
    new {controller="Home", action="index"}
);

The MyCustomRouteConstraint type above would check for x==0 etc in your example. Not sure exactly what you want to do, but this will allow you to check conditions before running and set additional route values etc.

See here for example of custom route constraints.


Alternativly, yes you can use a custom ActionFilter, just apply it to the controller class, and it will be called before any action is executed. Something like:

public class CheckXActionFilterAttribute : ActionFilterAttribute
{

      public override void OnActionExecuting(ActionExecutingContext filterContext)
      {
           if(x == 0)
           {
               // do something
               // e.g. Set ActionParameters etc
           }
           else
           {
               // do something else
           }
      }


}

Another option is to have all you controllers (or the relevant ones) inherit from a custom controller you make, and override :

OnActionExecuting

See here for details.

To do the same as the filter, or routing constraints.

Vyatka answered 16/4, 2010 at 3:42 Comment(0)
T
1

One way you can do this is to redirect to a different ActionMethod to show the view. Code example is in this discussion:

Redirecting to specified controller and action in asp.net mvc action filter

Turboelectric answered 16/4, 2010 at 3:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.