Autofac,MVC(带有ActionFilters),Web.Forms-依赖关系解决冲突 [英] Autofac, MVC (with ActionFilters), Web.Forms - dependency resolution conflict
问题描述
我有一个遗留的Web.Forms应用程序,该应用程序已部分重写为MVC. MVC部分使用autofac作为依赖项注入容器.
I've got a legacy Web.Forms app that been partially rewritten to MVC. MVC part uses autofac as a dependency injection container.
MVC部分已定义了自定义过滤器:
MVC part have custom filter defined:
public class CustomActionFilter : ActionFilterAttribute
{
protected ILogger Logger { get; set; }
public CustomActionFilter(ILogger logger) { Logger = logger; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Logger.Log("OnActionExecuting");
}
}
在web.config中禁用Web.Forms集成时,它可以正常工作.但是,当我尝试使用Web.Forms autofac集成时,我在autofac内部的某个地方找到了与AutofacFilterProvider
相关的NullReferenceException(堆栈跟踪).
It works fine when Web.Forms integration is disabled in web.config. Hovewer, when I try to use Web.Forms autofac integration, I've got the NullReferenceException related to AutofacFilterProvider
somewhere in autofac internals (stack trace).
- Global.asax.cs: http://pastebin.com/437Tnp0t
- web.config: http://pastebin.com/5pU6SH6c
- Global.asax.cs: http://pastebin.com/437Tnp0t
- web.config: http://pastebin.com/5pU6SH6c
请注意,CustomActionFilter
已注册为全局过滤器,因此已在autofac中注册:
Note that CustomActionFilter
is registered as global filter, thus it is registered with autofac:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(DependencyResolver.Current.GetService<CustomActionFilter>());
}
}
我尝试过:
- 为MVC和Web.Forms使用单独的容器-结果相同
- 使用属性注入代替构造函数-结果相同
- 明确触发web.forms页面上的依赖项解析(例如此)-有效
- using separate containers for MVC and Web.Forms - same result
- Use property injection instead of constructor - same result
- Explicitly trigger dependencies resolution on web.forms pages (like this) - worked
所以,问题是,有没有办法为MVC和web.forms部分提供幕后依赖解析.我是autofac的新手,而对于依赖项注入容器则是新手,所以我可能会错过一些显而易见的事情.
So, the question is, are there any way to provide behind-the-scenes dependency resolution both to MVC and web.forms part. I'm new to autofac and somewhat new to dependency injection containers in general, so I might just miss something obvious.
更新:错误与自定义过滤器无关.如果删除所有对自定义过滤器的引用,则错误行为仍然相同,即使是堆栈跟踪也是如此.
Update: error has nothing to do with custom filters. If I remove all references to custom filters the bug behavior still the same, even the stack trace.
推荐答案
实际上有两个错误?在Autofac中会导致此行为:
Actually there are two bugs? in Autofac which causing this behavior:
错误1::作为问题的修复的副作用351 AutofacDependencyResolver
需要在创建的请求绑定LifeTimeScope
中注册. MVC集成可以做到这一点,但Winforms集成当然不会.
Bug #1: As side effect of the fix of Issue 351 the AutofacDependencyResolver
needs to registered in the created Request bound LifeTimeScope
s. The MVC intergration does this but the Winforms integration of course does not.
错误? #2: RequestLifetimeScopeProvider
和ContainerProvider
都使用相同的键HttpContext.Current.Items
存储创建的ILifetimeScope
:
Bug? #2: Both the RequestLifetimeScopeProvider
and the ContainerProvider
stores the created ILifetimeScope
with the same key HttpContext.Current.Items
:
static ILifetimeScope LifetimeScope
{
get { return (ILifetimeScope)HttpContext.Current.Items[typeof(ILifetimeScope)]; }
set { HttpContext.Current.Items[typeof(ILifetimeScope)] = value; }
}
因此这里存在一些竞争条件,因为取决于首先执行哪个模块,WebForms或MVC交互ILifetimeScope会获胜.因此,如果WebForms模块获胜,则不会注册AutofacDependencyResolver
,您将获得漂亮的非描述性异常.
So there is a little bit race condition here because depending on which module gets executed first the WebForms or the MVC intergartion ILifetimeScope wins. So if the WebForms module wins the AutofacDependencyResolver
won't be registered and you get the nice non descriptive exception.
修复/解决方法:
但是有一个简单的解决方法:您只需要在ContainerProvider
requestLifetimeConfiguration
中注册AutofacDependencyResolver
,所以无论哪一个获胜(WebForm vs. MVC),AutofacDependencyResolver
都将始终被注册:>
But there is an simple workaround: you just need to register the AutofacDependencyResolver
in the ContainerProvider
requestLifetimeConfiguration
so no matter which one wins (WebForm vs. MVC) the AutofacDependencyResolver
will be always registered:
var autofacDependencyResolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(autofacDependencyResolver);
_containerProvider = new ContainerProvider(container, requestContainerBuilder =>
requestContainerBuilder.RegisterInstance(autofacDependencyResolver)
.As<AutofacDependencyResolver>());
这篇关于Autofac,MVC(带有ActionFilters),Web.Forms-依赖关系解决冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!