Lapenkov Vladimir
Lapenkov Vladimir

Reputation: 3218

dependency injection in mvc filter which is global

I use unity and then ninject in mvc4, mvc5. I inject service or dbcontext to action filter as public property this way:

 public class MyActionFilterAttribute: FilterAttribute,IActionFilter
{
    [Inject]
    public IDbContext DbContext { get; set; }
    [Inject]
    public IProductService ProductService { get; set; }


    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debug.WriteIf(DbContext == null, "db context is null");
        Debug.WriteIf(ProductService == null, "productservice is null");


    }
    public void OnActionExecuted(ActionExecutedContext filterContext)
    { }
}

}

If I register a global filter, filters.Add(new MyActionFilterAttribute()); DbContext and ProductService are always null. But if i mark [MyActionFilter] attribute to Controller everything works fine. I'd like to register some filter as global, please help.

Upvotes: 2

Views: 1441

Answers (2)

Pedro Benevides
Pedro Benevides

Reputation: 1980

The simple example is to register your filter globally in the NinjectWebCommon class, you can do like this:

kernel.BindFilter<MyActionFilterAttribute>(FilterScope.Global, 1).InRequestScope();

and remove the line from Global.asax

Upvotes: 1

Krzysztof Branicki
Krzysztof Branicki

Reputation: 7837

Wen you are registering global filters like this filters.Add(new MyActionFilterAttribute()); you are registering filter instance. This same instance will be used on every call. This instance doesn't have your dependencies populated because you created it yourself using default constructor instead of resolving it from the container. Of course you cant resolve instance of your filter during global filter registration because your dependencies (DbContext for example) need to be scoped per request.

So you have 4 options.

  • Decorate all your controllers with the action filter
  • Create controller base class, decorate this class with the action filter and then derive all your controllers from this class.
  • Use some form of service locator inside your action filter code to resolve your dependencies from the container every time they are needed. Then you can register your filter as a global filter.
  • Create custom IFilterProvider and resolve your filter from the container in the GetFilters method. Then register your provider FilterProviders.Providers.Add(new MyFilterProvider(diContainer));

Upvotes: 4

Related Questions