[英]WebApi 2, OWIN and AutoFac - change HttpContextBase dependency
Recently I decided that I would like to integrate test my WebApi 2 application. 最近,我决定要集成测试WebApi 2应用程序。 I decided to convert my application to OWIN compliant.
我决定将我的应用程序转换为OWIN兼容。 I have included all the NuGet packages and hooked it up with AutoFac middleware and so on.
我已经包含了所有的NuGet程序包,并将其与AutoFac中间件等连接起来。
However when I try to test the application with HttpClient
in in Main method of sample program, I get an error: 但是,当我尝试在示例程序的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)"
}
}
}
I isolated the cause: it's my service which has dependency on HttpContextBase
for storing and extracting something from cookies: 我隔离了原因:这是我的服务依赖于
HttpContextBase
来存储和从cookie中提取某些内容:
public CookieUserService(HttpContextBase httpContext)
and AutoFac can't initialize this class. 并且AutoFac无法初始化此类。 When I tried another implementation, without
HttpContextBase
, dependency it works. 当我尝试另一个没有
HttpContextBase
实现时,它可以工作。
So the question is: is there a way to get access to cookies while using OWIN, so I could refactor the service and get rid of HttContextBase
(and Web.dll
) dependecies? 因此,问题是:有一种方法可以在使用OWIN时访问cookie,以便我可以重构服务并摆脱
HttContextBase
(和Web.dll
)依赖项?
While switching to OWIN, all dependencies on System.Web and so on become invalid, as they are coupling tight the application with IIS hosting environment. 切换到OWIN时,对System.Web等的所有依赖关系都将变为无效,因为它们会将应用程序与IIS托管环境紧密结合在一起。 Therefore AutoFac is not able to inject
HttpContextBase
as dependency to my service, because it can't instan. 因此,AutoFac无法将
HttpContextBase
作为对我的服务的依赖关系注入,因为它无法实例化。
In order to overcome the problem, instead of using System.Web dependencies like HttpContextBase
, service should depend on OWIN specific interfaces, which provide abstraction between application and hosting environment. 为了解决该问题,服务应该使用OWIN特定的接口,而不是使用诸如
HttpContextBase
类的System.Web依赖项,后者在应用程序和托管环境之间提供抽象。
In my specific case, I changed the service to depend on IOwinContext, like so: 在我的特定情况下,我将服务更改为依赖于IOwinContext,如下所示:
public OwinCookieUserService(IOwinContext owinContext)
{
if (owinContext == null) throw new ArgumentNullException(nameof(owinContext));
_owinContext = owinContext;
}
After adding two additional NuGet packages: 添加两个附加的NuGet软件包后:
I was able to glue together AutoFac and OWIN in my Startup class: 我可以在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);
}
}
In my AutoFac mappings, I have the following routine that where I define my service dependency: 在我的AutoFac映射中,我具有以下例程,用于在其中定义我的服务依赖项:
....
builder.RegisterType<OwinCookieUserService>().AsImplementedInterfaces().InstancePerLifetimeScope();
....
That is basically it! 基本上就是这样! I didn't have to specifically setup mappings for OWIN interfaces and classes, it just works.
我不必专门为OWIN接口和类设置映射,它可以正常工作。 I hope that will help some of you folks in the future.
我希望这将对将来的某些人有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.