ASP.NET MVC 5 + Owin + SimpleInjector
ASP.NET MVC 5 + Owin + SimpleInjector
如果我从项目中删除 DI 库,使用 owin、webapi、mvc 和 DI (SimpleInjector) 的新 asp.net mvc 项目运行良好。但是,一旦引入,应用程序就会在为 DI 注册 OWIN 组件时崩溃。 OWIN 启动配置被命中并运行没有错误,但是当需要注册依赖项(如下所列)时,我收到以下错误:
An exception of type 'System.InvalidOperationException' occurred in Microsoft.Owin.Host.SystemWeb.dll but was not handled in user code
Additional information: No owin.Environment item was found in the context.
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>();
更新 - 完整堆栈跟踪
at
System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase
context) at
WebApplication1.App_Start.SimpleInjectorInitializer.<>c__DisplayClass6.b__2()
in
b:\temp\WebApplication1\WebApplication1\App_Start\SimpleInjectorInitializer.cs:line
41 at lambda_method(Closure ) at
SimpleInjector.Scope.CreateAndCacheInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration
2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration, Scope scope) at
SimpleInjector.Advanced.Internal.LazyScopedRegistration
2.GetInstance(Scope
scope) at lambda_method(Closure ) at
SimpleInjector.InstanceProducer.GetInstance()
我认为当您调用 Verify()
时会抛出异常。可能在那一行,但只有在调用委托时。
Simple Injector 允许以任何顺序进行注册,因此不会验证注册依赖项的存在性和正确性。此验证在第一次请求实例时完成,或者可以通过在注册过程结束时调用 .Verify()
来触发。
我怀疑你注册 OwinContext
只是因为你需要它来获得 IAuthenticationManager
.
您面临的问题是 OwinContext
仅在存在 HttpContext
时可用。在组合根中构建应用程序时,此上下文不可用。您需要的是一个检查应用程序阶段的委托和 return 一个与该阶段匹配的组件。您可以通过将 IAuthenticationManager
注册为:
container.RegisterPerWebRequest<IAuthenticationManager>(() =>
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication);
当代码运行在 'normal runtime stage' 并且存在 HttpContext
时,委托将 return Owin 控制 IAuthenticationManager
。
但是在注册过程结束时显式调用 Verify()
(这是高度 advisable 要做的!)时没有 HttpContext
。因此,我们将在验证容器期间创建一个新的 OwinContext
,并从这个新创建的 OwinContext
return 身份验证组件。但前提是容器确实在验证!
可以阅读完整详细的描述here,正如评论中已经提到的那样。
虽然问题不一样,但是答案是一样的my answer here。
问题是您正在将 HttpContextWrapper 注入应用程序并尝试在应用程序初始化期间使用其成员,但在应用程序生命周期的那个时刻,HttpContext 尚不可用。 HttpContext 包含 运行时状态 ,在一个特定用户的上下文中初始化应用程序没有意义。
要解决这个问题,您应该使用一个或多个 Abstract Factories 在运行时(当它可用时)而不是在应用程序初始化时访问 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);
如果我从项目中删除 DI 库,使用 owin、webapi、mvc 和 DI (SimpleInjector) 的新 asp.net mvc 项目运行良好。但是,一旦引入,应用程序就会在为 DI 注册 OWIN 组件时崩溃。 OWIN 启动配置被命中并运行没有错误,但是当需要注册依赖项(如下所列)时,我收到以下错误:
An exception of type 'System.InvalidOperationException' occurred in Microsoft.Owin.Host.SystemWeb.dll but was not handled in user code
Additional information: No owin.Environment item was found in the context.
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>();
更新 - 完整堆栈跟踪
at System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase context) at WebApplication1.App_Start.SimpleInjectorInitializer.<>c__DisplayClass6.b__2() in b:\temp\WebApplication1\WebApplication1\App_Start\SimpleInjectorInitializer.cs:line 41 at lambda_method(Closure ) at SimpleInjector.Scope.CreateAndCacheInstance[TService,TImplementation](ScopedRegistration
2 registration) at SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration
2 registration) at SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2 registration, Scope scope) at SimpleInjector.Advanced.Internal.LazyScopedRegistration
2.GetInstance(Scope scope) at lambda_method(Closure ) at SimpleInjector.InstanceProducer.GetInstance()
我认为当您调用 Verify()
时会抛出异常。可能在那一行,但只有在调用委托时。
Simple Injector 允许以任何顺序进行注册,因此不会验证注册依赖项的存在性和正确性。此验证在第一次请求实例时完成,或者可以通过在注册过程结束时调用 .Verify()
来触发。
我怀疑你注册 OwinContext
只是因为你需要它来获得 IAuthenticationManager
.
您面临的问题是 OwinContext
仅在存在 HttpContext
时可用。在组合根中构建应用程序时,此上下文不可用。您需要的是一个检查应用程序阶段的委托和 return 一个与该阶段匹配的组件。您可以通过将 IAuthenticationManager
注册为:
container.RegisterPerWebRequest<IAuthenticationManager>(() =>
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication);
当代码运行在 'normal runtime stage' 并且存在 HttpContext
时,委托将 return Owin 控制 IAuthenticationManager
。
但是在注册过程结束时显式调用 Verify()
(这是高度 advisable 要做的!)时没有 HttpContext
。因此,我们将在验证容器期间创建一个新的 OwinContext
,并从这个新创建的 OwinContext
return 身份验证组件。但前提是容器确实在验证!
可以阅读完整详细的描述here,正如评论中已经提到的那样。
虽然问题不一样,但是答案是一样的my answer here。
问题是您正在将 HttpContextWrapper 注入应用程序并尝试在应用程序初始化期间使用其成员,但在应用程序生命周期的那个时刻,HttpContext 尚不可用。 HttpContext 包含 运行时状态 ,在一个特定用户的上下文中初始化应用程序没有意义。
要解决这个问题,您应该使用一个或多个 Abstract Factories 在运行时(当它可用时)而不是在应用程序初始化时访问 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);