Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Questions on lifetime of Ninject-created action filters in MVC 3

I would like to use a global-scoped action filter in my MVC 3 application using Ninject; however, I'm trying to understand the lifetime of that filter, its dependencies, and how to introduce variations to its dependencies by decorating my controllers and/or action methods.

I'd like to have my filter type depend on objects whose lifetimes are bound to request scope, so, something like this:

public sealed class MyGlobalActionFilter : IActionFilter
{
    public MyGlobalActionFilter(IService1 svc1, IService2 svc2, RequestType reqType)
    {
        // code here
    }

    // IActionFilter implementation here...
}

... and in the module config ...

Bind<IService1>().To<ConcreteService1>().InRequestScope()
Bind<IService2>().To<ConcreteService2>().InRequestScope()
BindFilter<MyGlobalActionFilter>(FilterScope.Global, null)
    .WhenControllerHas<RequestTypeAttribute>()
    .WithConstructorArgumentFromControllerAttribute<RequestTypeAttribute>(
        "reqType", 
        x => x.RequestType
    );
BindFilter<MyGlobalActionFilter>(FilterScope.Global, null)
    .WhenActionMethodHas<RequestTypeAttribute>()
    .WithConstructorArgumentFromActionAttribute<RequestTypeAttribute>(
        "reqType", 
        x => x.RequestType
    );
BindFilter<MyGlobalActionFilter>(FilterScope.Global)
    .When(x => true)
    .WithConstructorArgument("reqType", RequestType.Undefined)

And an attribute on controllers and/or action methods to represent an application-specific "request type":

[RequestType(RequestType.Type1)]
public sealed class SomeController : Controller { /* code here*/ }

Am I understanding properly how this should work? Will a new instance of MyGlobalActionFilter get spun up and injected on each HTTP request? If this won't work, what am I missing, and what would be a better way to make this work?

Also, with injecting the RequestType, the BindFilter syntax here seems unnecessarily verbose, I'm not sure if it works like I expect, and it seems there would be a better way to inject a default RequestType into the action filter if a RequestTypeAttribute isn't present on the controller or the action method.

Please enlighten me!

like image 780
FMM Avatar asked Sep 15 '11 15:09

FMM


People also ask

Which action filter executes last in an MVC application?

Exception Filters − Exception filters are the last type of filter to run. You can use an exception filter to handle errors raised by either your controller actions or controller action results.

What are the action filters in MVC interview questions?

What are Action Filters in MVC? Action Filters are additional attributes that can be applied to either a controller section or the entire controller to modify the way in which action is executed. These attributes are special . NET classes derived from System.

What step is required to apply a filter globally to every action in your application?

As Global Filter You need to add your filter globally, to add your filter to the global filter. You first need to add it on Global. asax file. You can use FilterConfig.


1 Answers

I havn't seen an official documentation from Microsoft when and how often IFilterProvider is called exactly. But from my observations it seems to be called once for each request. This means that transient bound filters are basically InRequestScope bound with the difference that they aren't disposed by Ninject at the end of the request.

There are some changes you should do:

  • Do not derive from ActionFilterAttribute but implement IActionFilter instead to prevent that it is accidentially used as attribute.
  • Rethink the use of FilterScope.Global for all bindings. I consider it as bad practice to have filters on actions/controllers running with global priority.

Also be aware that a filter for each matching binding is created and executed. This means that currently the one with RequestType.Undefined is run on every request independent of whether there is an attribute on the action or controller. Additionally, the ones for action and controllers are executed if there is a attribute on them.

like image 76
Remo Gloor Avatar answered Oct 17 '22 13:10

Remo Gloor