ASP.NET MVC 5 + Owin + SimpleInjector

本文关键字:Owin SimpleInjector NET MVC ASP | 更新日期: 2023-09-27 18:37:18

如果我从项目中删除DI lib,那么使用owin、webapi、mvc和DI(SimpleInjector(的新asp.net mvc项目运行良好。然而,一旦引入,该应用程序在为DI注册OWIN组件时就会崩溃。OWIN启动配置被命中并运行无错误,但当需要注册依赖项(如下所示(时,我收到以下错误:

Microsoft.Owin.Host.SystemWeb.dll中出现"System.InvalidOperationException"类型的异常,但未在用户代码中处理

附加信息:无owin。在上下文中找到环境项。

SimpleInjector注册代码:

container.RegisterPerWebRequest<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>());
container.RegisterPerWebRequest<HttpContextBase>(() => new HttpContextWrapper(HttpContext.Current));
// app fails on call to line below...
container.RegisterPerWebRequest(() => container.GetInstance<HttpContextBase>().GetOwinContext());
container.RegisterPerWebRequest(() => container.GetInstance<IOwinContext>().Authentication);
container.RegisterPerWebRequest<DbContext, ApplicationDbContext>();

更新-完整堆栈跟踪

在System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase上下文(WebApplication1.App_Start.SimpleInjectorInitializer.<>c_DisplayClass6.b_2((在里面b: ''temp''WebApplication1''WebApplication1''App_Start''SimpleInjectorInitializer.cs:line41在lambda_method(闭包(SimpleInjector.Scope.CreateAndCacheInstance[TService,TIimplementation](ScopedRegistration 2 registration) at SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration 2注册(SimpleInjector.Scope.GetInstance[TService,TIimplementation](ScopedRegistration 2 registration, Scope scope) at SimpleInjector.Advanced.Internal.LazyScopedRegistration 2.GetInstance(Scopescope(的lambda_method(闭包(SimpleInjector.InstanceProducer.GetInstance((

ASP.NET MVC 5 + Owin + SimpleInjector

我认为在调用Verify()时会抛出异常。可能在那一行,但仅当调用代理时。

Simple Injector允许以任何顺序进行注册,因此不会验证注册依赖项的存在和正确性。此验证在第一次请求实例时完成,或者可以通过在注册过程结束时调用.Verify()来触发。

我怀疑你注册OwinContext只是因为你需要它来获得IAuthenticationManager

您面临的问题是,OwinContext只有在存在HttpContext时才可用。在组合根中生成应用程序时,此上下文不可用。您需要的是一个委托,它检查应用程序的阶段并返回与该阶段匹配的组件。您可以将IAuthenticationManager注册为:

container.RegisterPerWebRequest<IAuthenticationManager>(() => 
    AdvancedExtensions.IsVerifying(container) 
        ? new OwinContext(new Dictionary<string, object>()).Authentication 
        : HttpContext.Current.GetOwinContext().Authentication); 

当代码在"正常运行时阶段"运行并且存在HttpContext时,委托将返回Owin控制的IAuthenticationManager

但是,当在注册过程结束时显式调用Verify()(这是非常可取的!(时,没有HttpContext。因此,我们将在验证容器期间创建一个新的OwinContext,并从这个新创建的OwinContext返回Authentication组件。但前提是容器确实在验证!

正如评论中已经提到的那样,可以在这里阅读完整而详细的描述。

虽然问题不同,但答案与我在这里的答案相同。

问题是,您正在将HttpContextWrapper注入到应用程序中,并试图在应用程序初始化期间使用其成员,但在应用程序生命周期的那个阶段,HttpContext还不可用。HttpContext包含运行时状态,在特定用户的上下文中初始化应用程序是没有意义的。

为了解决这个问题,您应该在运行时(当HttpContext可用时(而不是在应用程序初始化时使用一个或多个抽象工厂来访问HttpContext,并使用DI将工厂注入到您的服务中。

使用Ric.Net的答案也可能有效,但每次初始化应用程序时,它都会抛出一个异常

"Ric.Net"的答案为我指明了正确的方向,但为了允许更改新的SimpleInjector,必须更改以下代码(因为RegisterPerWebRequest已删除(:

        container.Register<IAuthenticationManager>(() => AdvancedExtensions.IsVerifying(container)
                    ? new OwinContext(new Dictionary<string, object>()).Authentication
                    : HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);

此外,必须将以下两个注册添加到容器中,以允许"container.Verify(("正确工作:

        container.Register<ApplicationUserManager>(Lifestyle.Scoped);
        container.Register<ApplicationSignInManager>(Lifestyle.Scoped);