Asp.net mvc 3 使用数据库的MVC3操作过滤器(EF 4.1 DBContext,Ninject)
我试图在一个操作上设置一个“授权”过滤器,创建我自己的ActionFilterAttribute,在这里我进行数据库查找,以确定用户是否有权访问某个资源 在继承自ActionFilterAttribute的类上,我创建了一个注入(Ninject)属性来保存我用于数据库访问的服务。我有一个无参数构造函数,这样我就可以在我的操作中使用它作为属性。在“OnActionExecuting”方法中,我能够访问注入的属性(它不是null),但它使用的基本DBCotext是关闭的 该工作正常,直到MVC3的RTM,其中发行说明说明: 中断更改: 在以前版本的ASP.NET MVC中,操作筛选器是根据创建的 除少数情况外,请求。这 行为从来都不是保证 行为,而仅仅是一种实现 过滤器的详细信息和合同 认为他们是无国籍的。在里面 ASP.NET MVC 3,过滤器缓存更多 积极地。因此,任何习俗 不正确存储的操作筛选器 实例状态可能已损坏 第一次使用此筛选器时,它会按预期工作,但如果我刷新页面或其他用户访问此筛选器,则会出现错误: 无法完成该操作 因为DbContext已经 处置 这是我想我应该期待的,因为有了突破性的变化Asp.net mvc 3 使用数据库的MVC3操作过滤器(EF 4.1 DBContext,Ninject),asp.net-mvc-3,ninject,entity-framework-4.1,Asp.net Mvc 3,Ninject,Entity Framework 4.1,我试图在一个操作上设置一个“授权”过滤器,创建我自己的ActionFilterAttribute,在这里我进行数据库查找,以确定用户是否有权访问某个资源 在继承自ActionFilterAttribute的类上,我创建了一个注入(Ninject)属性来保存我用于数据库访问的服务。我有一个无参数构造函数,这样我就可以在我的操作中使用它作为属性。在“OnActionExecuting”方法中,我能够访问注入的属性(它不是null),但它使用的基本DBCotext是关闭的 该工作正常,直到MVC3的R
我的问题是,完成我需要做的事情的首选/推荐方式是什么?这应该在ActionFilterAttribute中,还是应该在其他地方执行此“授权”?我会在
应用程序中执行身份验证,并使用线程.CurrentPrincipal
在属性中执行授权,但您的方法也应该有效。您只需要计算一个事实,即DbContext对于每个请求都是不同的,但您的属性不会。类似这样的东西应该可以做到这一点(我假设您使用的是dependencysolver
):
我已经为此奋斗了一段时间,终于解决了我的问题。所以这里是我的解决方案,希望它能帮助其他人
设置:
1.我有一个MVC3项目,一个自定义操作过滤器,通过业务服务使用EF5访问数据库。
2.我使用Unity和Unity.MVC来解决每个请求的依赖关系。
3.我在自定义操作过滤器中使用属性注入,因为它有一个无参数构造函数
结果呢。
依赖项注入对于操作使用的所有服务都能正常工作,my EF DbContext在每个请求结束时都能正确处理
问题
虽然我的属性依赖关系在我的自定义操作筛选器中得到解决,但它包含一个过时的DbContext实例(例如,它似乎是从上一个请求中缓存的)
如前几篇文章所述,MVC3在过滤器缓存方面更具攻击性,过滤器的状态不可依赖。因此,建议解决OnActionExecuting方法中的依赖关系。因此,我删除了注入的属性,并在unity容器上执行了名为resolve的操作。然而,我仍然得到了一个过时的DbContext版本。数据库中的任何更改都已在我的主操作中正确查询,但自定义操作筛选器未将其拾取
解决方案。
MVC通过使用子容器并在每个请求结束时处理这些子容器来管理每个请求的生存期。通过从unity容器中解析操作筛选器中的依赖项,我是从父容器中解析的,而父容器在每个请求中都没有处理
所以而不是
IoC.Instance.CurrentContainer.Resolve<IService>();
现在,构造函数解析您的服务并将其存储为私有只读。现在可以在OnActionExecuting函数中使用它。单元测试现在可以调用第二个构造函数并注入一个mock。这正是我使用的方法,但是使用这种方法违背了使用“注入”属性或构造函数的目的,不是吗?每当我需要访问我的一项服务时,使用DependencyResolver是一种好方法吗?使用依赖项注入的目的是让您可以动态地解析依赖项-通常用于整个实例,但在本例中仅用于一种方法-这就是我的看法(但我不是DI方面的专家,所以我可能是错的)。DependencyResolver是特定于mvc的,因此我认为在mvc上下文中使用它是有效的,但是,如果您想将IServiceProvider
映射到您的Kernel
实例,并将IServiceProvider
注入属性,然后使用该属性而不是DependencyResolver。我也遇到了同样的问题,最终使用了DependencyResolver。据我所知,如果DI容器管理每个请求的DbContext,那么构造函数注入将不起作用,因为过滤器是在请求外部实例化的。(我使用的是Ninject和.InRequestScope())你有没有找到解决这个问题的方法……有相同的问题。
IoC.Instance.CurrentContainer.Resolve<IService>();
var childContainer = HttpContext.Current.Items["perRequestContainer"] as IUnityContainer;
var service = childContainer.Resolve<IServcie>();
public MyCustomActionfilter() : this(((IUnityContainer)HttpContext.Current.Items["perRequestContainer"].Resolve<IService>())
public MyCustomActionfilter(IService service)
{
this.service = service;
}