14

I have some code in my application that I need to execute on every request, before anything else executes (even before authentication). So far I've been using the Application_BeginRequest event in my Global.asax, and this has worked fine. But this code needs to hit the database, and doing this from Global.asax doesn't feel right for some reason. Also, the Ninject.MVC3 nuget I'm using won't inject dependencies into my HttpApplication ctor.

So what I decided to do is move this code into its own global action filter. The problem I'm having now is that no matter what Order or FilterScope I give this filter, I can't get it to execute first; my authorization filter always beats it. MSDN seems to confirm this:

Filter Order

Filters run in the following order:

  1. Authorization filters
  2. Action filters
  3. Response filters
  4. Exception filters

For example, authorization filters run first and exception filters run last. Within each filter type, the Order value specifies the run order. Within each filter type and order, the Scope enumeration value specifies the order for filters.

I know I can use an HttpModule, but that doesn't feel very MVCish, so I am trying to exhaust all possiblities before going that route, which leads to my question:

Is there a BeginRequest equivalent for global action filters?

Daniel Liuzzi
  • 16,807
  • 8
  • 52
  • 57

1 Answers1

16

You could do this in the Initialize method of a base controller.

Another possibility is to register a global filter:

public class MyGlobalFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // that's gonna be hit
    }
}

and in the RegisterGlobalFilters event of your Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new MyGlobalFilter());
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I'm using DI, so the new operator is out :( Initialize in a base controller did work. However, being forced to inherit from a base type feels a bit restricting; the whole reason I was trying to accomplish this with filters (or -albeit more undesirably- HTTP modules) is because of their modularity. – Daniel Liuzzi Feb 03 '11 at 13:17
  • @Daniel, what prevents you to do `filters.Add(DIContainer.Get());` if you don't want to use the `new` operator? – Darin Dimitrov Feb 03 '11 at 15:24
  • there's nothing preventing me to do that. But I would rather not call the container directly, as that would be service location, not inversion of control. Also, I don't feel comfortable making my code so tightly coupled to Ninject, so I'm trying to keep my kernel.Get()'s to a minimum. – Daniel Liuzzi Feb 03 '11 at 18:48
  • 1
    @Daniel, then you probably would find the [following blog post](http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html) useful. – Darin Dimitrov Feb 03 '11 at 19:10