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

时间:2015-09-12 08:59:08

标签: c# httprequest asp.net-web-api2 owin autofac

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

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

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)" } } } 来存储和从Cookie中提取内容:

HttpContextBase

并且AutoFac无法初始化此类。当我尝试另一个没有public CookieUserService(HttpContextBase httpContext)的实现时,依赖它就可以了。

所以问题是:有没有办法在使用OWIN时访问cookie,所以我可以重构服务并摆脱HttpContextBase(和HttContextBase)依赖?

1 个答案:

答案 0 :(得分:0)

切换到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
  3. 我能够在我的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接口和类设置映射,它只是工作。我希望这将有助于你们中的一些人。