最近,我决定要集成测试WebApi 2应用程序。我决定将我的应用程序转换为OWIN兼容。我已经包含了所有的NuGet程序包,并将其与AutoFac中间件连接起来,依此类推。
但是,当我尝试使用HttpClient
示例程序的Main方法中的in测试应用程序时,出现错误:
{
"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
对我的服务的依赖关系,因为它不能实例化。
为了解决该问题,HttpContextBase
服务应该依赖于OWIN特定的接口,而不是使用System.Web依赖项(如),该接口提供应用程序和托管环境之间的抽象。
在我的特定情况下,我将服务更改为依赖于IOwinContext,如下所示:
public OwinCookieUserService(IOwinContext owinContext)
{
if (owinContext == null) throw new ArgumentNullException(nameof(owinContext));
_owinContext = owinContext;
}
添加两个附加的NuGet程序包后:
我可以在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接口和类设置映射,它可以正常工作。我希望这将对将来的某些人有所帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句