mvc过滤器中的依赖注入是全局的

时间:2015-12-17 09:10:34

标签: asp.net-mvc-4 dependency-injection asp.net-mvc-5

我使用unity然后在mvc4,mvc5中使用ninject。 我将服务或dbcontext注入动作过滤器作为公共属性:

 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)
    { }
}

}

如果我注册了全局过滤器,filters.Add(new MyActionFilterAttribute()); DbContext和ProductService始终为null。 但是如果我将[MyActionFilter]属性标记为Controller,一切正常。 我想将一些过滤器注册为全球过滤器,请帮忙。

2 个答案:

答案 0 :(得分:4)

你正在注册像filters.Add(new MyActionFilterAttribute());这样的全局过滤器,你正在注册过滤器实例。每个呼叫都将使用相同的实例。此实例没有填充依赖项,因为您使用默认构造函数自己创建它,而不是从容器中解析它。当然,在全局过滤器注册期间,您无法解析过滤器的实例,因为您的依赖项(例如DbContext)需要根据请求确定范围。

所以你有4个选择。

  • 使用操作过滤器
  • 装饰所有控制器
  • 创建控制器基类,使用操作过滤器修饰此类,然后从此类派生所有控制器。
  • 在操作过滤器代码中使用某种形式的服务定位器,以便在每次需要时从容器中解析依赖关系。然后,您可以将过滤器注册为全局过滤器。
  • 创建自定义IFilterProvider并使用GetFilters方法从容器中解析过滤器。然后注册您的提供商FilterProviders.Providers.Add(new MyFilterProvider(diContainer));

答案 1 :(得分:1)

简单示例是在NinjectWebCommon类中全局注册过滤器,您可以这样做:

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

并从Global.asax中删除该行