Unity.WebApi | 确保控制器具有无参数的公共构造函数

我在ASP.NET WebApi解决方案中使用Unity.WebApi NuGet包(Unity 4.0.1和Unity.WebApi 5.2.3)。 我面临的问题是,在尝试运行代码时,我收到错误: Make sure that the controller has a parameterless public constructor 。 我在这里搜索过类似的post,但我找不到任何符合我问题的post。

请不要只说“添加无参数构造函数”,因为它显示您显然不知道IoC是什么以及为什么该语句完全没有意义并且违背了IoC的目的。 我之所以这么说,是因为我在迄今为止看过的很多其他主题中看到了这一点。

这是我的Startup.cs(我正在使用Owin,所以我没有Global.asax):

 public void Configuration(IAppBuilder app) { var config = new HttpConfiguration(); config.MapHttpAttributeRoutes(); // Registering unity stuff UnityConfig.RegisterComponents(); app.UseWebApi(config); } 

这是我的UnityConfig.cs:

 public static class UnityConfig { public static void RegisterComponents() { var container = new UnityContainer(); // Register controller container.RegisterType(); // Register interface container.RegisterType(); GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container); } } 

这是我的API控制器:

 public class MyController : ApiController { private IService service public MyController(IService service) { this.service = service; } public IHttpActionResult Get() { return Ok("All systems go!"); } } 

编辑

我拿出了使用声明,因为人们很难理解无论是否存在using语句都会出现问题。

根据我的经验,发生这种情况有两种不同的情况。

1.确保可以解析Service构造函数中的所有参数。 它有没有注册的依赖项吗?

确保控制器在Unity中具有无参数的公共构造函数

2.确保使用Web API注册Unity。 像这样:

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Routes and other stuff here... var container = IocContainer.Instance; // Or any other way to fetch your container. config.DependencyResolver = new UnityDependencyResolver(container); } } 

这里的例子:

将dependency injectionWeb API控制器

http://codeclimber.net.nz/archive/2015/02/20/Using-Entity-Framework-within-an-Owin-hosted-Web-API-with.aspx

编辑1:

正如评论中提到的@ NightOwl888,您不应该丢弃容器。 注册在容器上注册,当容器被丢弃时,它将不知道如何解决依赖关系。 这可能会导致您看到的错误。

编辑2:

既然你正在使用Owin,你应该能够做到这样的事情:

  public void Configuration(IAppBuilder appBuilder) { // Configure Web API for self-host. HttpConfiguration config = new HttpConfiguration(); config.DependencyResolver = new UnityDependencyResolver( UnityConfig.GetConfiguredContainer()); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); appBuilder.UseWebApi(config); } 

并将您的UnityConfig更新为:

  public static class UnityConfig { public static IUnityContainer GetConfiguredContainer() { var container = new UnityContainer(); // Register controller container.RegisterType(); // Register interface container.RegisterType(); //This is done in Startup instead. //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container); return container; } } 

从这个来源: 如何在OwinStartup时使用DI容器

http://damienbod.com/2013/10/01/self-host-webapi-with-owin-and-unity/

在此方法中,HttpConfiguration.DependencyResolver设置为UnityDependencyResolver实例。 这是必需的,以便可以在webApi控制器中使用构造函数注入。 UnityDependencyResolver类与Unity.WebApi.UnityDependencyResolver类完全相同。 未使用Unity.WebApi,因为这是一个自托管的OWIN应用程序。

还有一个可能的调查路径和原因。 我在我的全局exception处理程序上设置了断点,并查看了我的exception实例上的嵌套exception属性。 我得到的错误没有一个可访问的构造函数,这是真的,因为我想注入的类型确实有一个私有构造函数(我正在重构一个单例)。

DependencyResolver设置为您在Startup创建的HttpConfiguration ,而不是GlobalConfiguration.Configuration ,并确保所有服务构造函数都是公共的,希望这有助于

确保正在正确解析任何已注入的嵌套类型。 即使嵌套类型被错误地解析,您也会在控制器级别上收到错误消息。

我正在使用Unity 4.0.1版本,在我的例子中,嵌套依赖Repository有两个公共构造函数,Unity没有设法选择无参数构造函数。

因此,我刚刚将另一个指定为受保护以快速解决问题。

  public Repository() : this( ... ) { ... } // if need to make public, make sure that the dependency injection container // will choose the parameterless constructor; // Unity has had issues with that by default protected Repository(DbContext context) : base() { ... } 

IMO,Unity本可以设法找到“可以调用”的构造函数 – 因为它没有注册DbContext(或任何派生的上下文)。

请注意,默认情况下, Unity选择具有最大参数数量的构造函数。

所以,是的,也可以用这里和这里描述的InjectionConstructorAttribute来装饰正确的构造函数 – 但我甚至在我的数据访问层中没有Unity引用(并且不想)。

请告诉我这些行为是否在以后的版本中发生了变化。