Unity IoC 不会将依赖项注入 Web API Controller
Unity IoC does not inject dependency into Web API Controller
我刚开始使用 Unity,但我的问题是每当我调用我的 Web 服务时,我都会收到一个异常说明
"Make sure that the controller has a parameterless public constructor"
我已经学习了多个教程,但仍然遇到同样的问题。
在我的 WebApiConfig class 的注册函数中,我有
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
这是我的 UnityResolver class
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
我没有注册任何控制器,因为每个教程都声称我不需要这样做。这是我的实际控制人
public class Controller: ApiController
{
private IValidator _validator;
public Controller(IValidator validator)
{
this._validator = validator;
}
[HttpPost]
public void ReceiveIPN()
{
}
}
有人知道我可能做错了什么吗?谢谢!
编辑 1:这是验证器 class 的 "implementation"。它很空,因为在解决 Unity 问题之前我不想在这里引入错误。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class Validator: IValidator
{
public bool ValidateIPN(string body)
{
throw new NotImplementedException();
}
}
编辑 2:这是我尝试使用 Fiddler
调用网络 api 路由时得到的完整错误响应
{"message":"An error has occurred.","exceptionMessage":"An error
occurred when trying to create a controller of type 'Controller'. 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) at
System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage
request) at
System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()","innerException":{"message":"An
error has occurred.","exceptionMessage":"Type 'Project.Controller'
does not have a default
constructor","exceptionType":"System.ArgumentException","stackTrace":"
at System.Linq.Expressions.Expression.New(Type type) at
System.Web.Http.Internal.TypeActivator.Create[TBase](Type
instanceType) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage
request, Type controllerType, Func`1& activator) at
System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage
request, HttpControllerDescriptor controllerDescriptor, Type
controllerType)"}}
您的 Unity 容器可能正在处理,因为它仅在您的 WebApiConfig.Register()
方法的范围内定义。如果您将容器定义为 Global 的成员,它将在应用程序的整个生命周期内保留您的容器,它应该可以工作。
编辑:也不要忘记在 Application_End 上处理容器。
所以,在用头撞墙几个小时后,我发现这不起作用,因为我的项目中有一个 OWIN/Katana Startup.cs class。现在我不知道这里到底发生了什么,所以如果能提供更多信息就更好了。
基本上,因为我使用的是 OWIN/Katana,所以我有一个 Startup.cs 文件,它创建了一个新的 HttpConfiguration 对象并对其进行了配置,类似于 WebApiConfig.cs class。
private void ConfigureWebApi(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>();
config.DependencyResolver = new UnityDependencyResolver(container);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
看起来代码首先通过 WebApiConfig 的 Register 函数运行,然后用 Startup.cs 文件中生成的对象覆盖 HttpConfiguration 对象。我必须将我的容器设置内容移到这里才能使其正常工作。
抱歉我之前没有提到 OWIN 的东西。这对我来说是相当新的,我没有意识到它是相关的。希望这可以避免其他人遭受我刚刚经历的痛苦。
我知道这是一个旧的 post 但由于我 运行 遇到了同样的问题,解决方案是简单地将配置对象传递给 Unity 注册函数并使用其中的 DependencyResolver实例:
编辑: 刚刚注意到已接受的答案确实如此......对于垃圾邮件感到抱歉;-)
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// register your services here...
// replace...
/* GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); */
// with this:
config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
- 通过nuget包在项目中安装Unity.mvc5和Unity.WebApi
- 按照下行指定全命名空间
示例:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
我刚开始使用 Unity,但我的问题是每当我调用我的 Web 服务时,我都会收到一个异常说明
"Make sure that the controller has a parameterless public constructor"
我已经学习了多个教程,但仍然遇到同样的问题。
在我的 WebApiConfig class 的注册函数中,我有
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
这是我的 UnityResolver class
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Web.Http.Dependencies;
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
我没有注册任何控制器,因为每个教程都声称我不需要这样做。这是我的实际控制人
public class Controller: ApiController
{
private IValidator _validator;
public Controller(IValidator validator)
{
this._validator = validator;
}
[HttpPost]
public void ReceiveIPN()
{
}
}
有人知道我可能做错了什么吗?谢谢!
编辑 1:这是验证器 class 的 "implementation"。它很空,因为在解决 Unity 问题之前我不想在这里引入错误。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
public class Validator: IValidator
{
public bool ValidateIPN(string body)
{
throw new NotImplementedException();
}
}
编辑 2:这是我尝试使用 Fiddler
调用网络 api 路由时得到的完整错误响应{"message":"An error has occurred.","exceptionMessage":"An error occurred when trying to create a controller of type 'Controller'. 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) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()","innerException":{"message":"An error has occurred.","exceptionMessage":"Type 'Project.Controller' does not have a default constructor","exceptionType":"System.ArgumentException","stackTrace":" at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)"}}
您的 Unity 容器可能正在处理,因为它仅在您的 WebApiConfig.Register()
方法的范围内定义。如果您将容器定义为 Global 的成员,它将在应用程序的整个生命周期内保留您的容器,它应该可以工作。
编辑:也不要忘记在 Application_End 上处理容器。
所以,在用头撞墙几个小时后,我发现这不起作用,因为我的项目中有一个 OWIN/Katana Startup.cs class。现在我不知道这里到底发生了什么,所以如果能提供更多信息就更好了。
基本上,因为我使用的是 OWIN/Katana,所以我有一个 Startup.cs 文件,它创建了一个新的 HttpConfiguration 对象并对其进行了配置,类似于 WebApiConfig.cs class。
private void ConfigureWebApi(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var container = new UnityContainer();
container.RegisterType<IValidator, Validator>();
config.DependencyResolver = new UnityDependencyResolver(container);
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
看起来代码首先通过 WebApiConfig 的 Register 函数运行,然后用 Startup.cs 文件中生成的对象覆盖 HttpConfiguration 对象。我必须将我的容器设置内容移到这里才能使其正常工作。
抱歉我之前没有提到 OWIN 的东西。这对我来说是相当新的,我没有意识到它是相关的。希望这可以避免其他人遭受我刚刚经历的痛苦。
我知道这是一个旧的 post 但由于我 运行 遇到了同样的问题,解决方案是简单地将配置对象传递给 Unity 注册函数并使用其中的 DependencyResolver实例:
编辑: 刚刚注意到已接受的答案确实如此......对于垃圾邮件感到抱歉;-)
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// register your services here...
// replace...
/* GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); */
// with this:
config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}
- 通过nuget包在项目中安装Unity.mvc5和Unity.WebApi
- 按照下行指定全命名空间
示例:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new Unity.Mvc5.UnityDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
}