繁体   English   中英

WebApi 2,OWIN和AutoFac-更改HttpContextBase依赖项

[英]WebApi 2, OWIN and AutoFac - change HttpContextBase dependency

最近,我决定要集成测试WebApi 2应用程序。 我决定将我的应用程序转换为OWIN兼容。 我已经包含了所有的Nu​​Get程序包,并将其与AutoFac中间件等连接起来。

但是,当我尝试在示例程序的Main方法中使用HttpClient测试应用程序时,出现错误:

{
  "Message":"An error has occurred.",
  "ExceptionMessage":"An error occurred when trying to create a controller of type 'DinnerListController'. Make sure that the controller has a parameterless public constructor.",
  "ExceptionType":"System.InvalidOperationException",
  "StackTrace":"   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)\r\n   at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
  "InnerException":{
    "Message":"An error has occurred.",
    "ExceptionMessage":"An exception was thrown while executing a resolve operation. See the InnerException for details. ---> Value cannot be null.\r\nParameter name: httpContext (See inner exception for details.)",
    "ExceptionType":"Autofac.Core.DependencyResolutionException",
    "StackTrace":"   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)\r\n   at Autofac.ResolutionExtensions.ResolveOptionalService(IComponentContext context, Service service, IEnumerable`1 parameters)\r\n   at Autofac.Integration.WebApi.AutofacWebApiDependencyScope.GetService(Type serviceType)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)\r\n   at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)",
    "InnerException":{
      "Message":"An error has occurred.",
      "ExceptionMessage":"Value cannot be null.\r\nParameter name: httpContext",
      "ExceptionType":"System.ArgumentNullException",
      "StackTrace":"   at System.Web.HttpContextWrapper..ctor(HttpContext httpContext)\r\n   at Autofac.Integration.Mvc.AutofacWebTypesModule.<Load>b__0(IComponentContext c)\r\n   at Autofac.RegistrationExtensions.<>c__DisplayClass10`1.<Register>b__f(IComponentContext c, IEnumerable`1 p)\r\n   at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass1`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)\r\n   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.<Execute>b__0()\r\n   at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)\r\n   at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.<CanSupplyValue>b__0()\r\n   at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()\r\n   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.<Execute>b__0()\r\n   at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)\r\n   at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.<CanSupplyValue>b__0()\r\n   at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()\r\n   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.<Execute>b__0()\r\n   at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)\r\n   at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Registration.ExternalRegistrySource.<>c__DisplayClass8.<RegistrationsFor>b__3(IComponentContext c, IEnumerable`1 p)\r\n   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.InstanceLookup.Execute()\r\n   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)\r\n   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)"
    }
  }
}

我隔离了原因:这是我的服务依赖于HttpContextBase来存储和从cookie中提取某些内容:

public CookieUserService(HttpContextBase httpContext)

并且AutoFac无法初始化此类。 当我尝试另一个没有HttpContextBase实现时,它可以工作。

因此,问题是:有一种方法可以在使用OWIN时访问cookie,以便我可以重构服务并摆脱HttContextBase (和Web.dll )依赖项?

切换到OWIN时,对System.Web等的所有依赖关系都将变为无效,因为它们会将应用程序与IIS托管环境紧密结合在一起。 因此,AutoFac无法将HttpContextBase作为对我的服务的依赖关系注入,因为它无法实例化。

为了解决该问题,服务应该使用OWIN特定的接口,而不是使用诸如HttpContextBase类的System.Web依赖项,后者在应用程序和托管环境之间提供抽象。

在我的特定情况下,我将服务更改为依赖于IOwinContext,如下所示:

public OwinCookieUserService(IOwinContext owinContext)
{
    if (owinContext == null) throw new ArgumentNullException(nameof(owinContext));  
    _owinContext = owinContext;
}

添加两个附加的NuGet软件包后:

  1. Autofac.Owin
  2. Autofac.WebApi2.Owin

我可以在Startup类中将AutoFac和OWIN粘合在一起:

public class Startup
{
   public void Configuration(IAppBuilder appBuilder)
   {
       var httpConfiguration = new HttpConfiguration();
       ...
       AutoFacConfig.ConfigureAutoFac(httpConfiguration);
       appBuilder.UseAutofacMiddleware(AutoFacConfig.Container);
       appBuilder.UseAutofacWebApi(httpConfiguration);
       appBuilder.UseWebApi(httpConfiguration);
   }
}

在我的AutoFac映射中,我具有以下例程,用于在其中定义我的服务依赖项:

....
    builder.RegisterType<OwinCookieUserService>().AsImplementedInterfaces().InstancePerLifetimeScope();
....

基本上就是这样! 我不必专门为OWIN接口和类设置映射,它可以正常工作。 我希望这将对将来的某些人有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM