Autofac,MVC(带有ActionFilters),Web.Forms-依赖关系解决冲突 [英] Autofac, MVC (with ActionFilters), Web.Forms - dependency resolution conflict

查看:169
本文介绍了Autofac,MVC(带有ActionFilters),Web.Forms-依赖关系解决冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个遗留的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

请注意,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>());
    }
}

我尝试过:

  1. 为MVC和Web.Forms使用单独的容器-结果相同
  2. 使用属性注入代替构造函数-结果相同
  3. 明确触发web.forms页面上的依赖项解析(例如)-有效
  1. using separate containers for MVC and Web.Forms - same result
  2. Use property injection instead of constructor - same result
  3. 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 LifeTimeScopes. The MVC intergration does this but the Winforms integration of course does not.

错误? #2: RequestLifetimeScopeProviderContainerProvider都使用相同的键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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆