【问题标题】:Unity.WebApi | Make sure that the controller has a parameterless public constructorUnity.WebApi |确保控制器有一个无参数的公共构造函数
【发布时间】:2016-04-28 11:04:10
【问题描述】:

我在 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。我在这里搜索过类似的主题,但找不到任何与我的问题匹配的主题。

请不要只说“添加无参数构造函数”,因为它表明您显然不知道 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<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            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 语句,因为人们很难理解无论 using 语句是否存在都会出现问题。

【问题讨论】:

  • 您能分享有关服务类的详细信息吗?您是否缺少注册 Service 类所需的任何类?
  • 可能是您的容器在 MVC 实际使用它之前就被处置了吗?它会抛出这个错误是不合逻辑的,但也许。尝试将 var container = new UnityContainer() 从 using 块中取出。
  • Noor 没有细节可以分享。假设它所做的只是有一个打印“Hello World”的方法。 NightOwl888 我最初是这样做的,所以事实并非如此。在试图解决这个问题时,使用后来出现了。我认为这很奇怪,因为它是基于 Owin 的,但我不确定。
  • @NightOwl888 是正确的。从 using 语句中取出统一容器和 http 配置。在收到第一个 Web 请求之前,它们都会被处理掉。
  • @TylerOhlsen 无论使用是否存在,都会导致相同的错误。

标签: c# asp.net-web-api dependency-injection inversion-of-control unity-container


【解决方案1】:

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

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

Make sure that the controller has a parameterless public constructor in 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);
    }
}

这里的例子:

Injecting Dependency into Web API Controller

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

编辑 1:

正如 cmets 中提到的 @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<MyController>();

            // Register interface
            container.RegisterType<IService, Service>();

            //This is done in Startup instead.
            //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
            return container;
    }
}

来自此来源: How to use DI container when OwinStartup

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

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

【讨论】:

  • 请参考我的 cmets 回答 NightOwl 的问题。 using 语句是在这些问题发生之后出现的,它是在尝试解决问题的过程中添加的。使用是否存在都没关系,我仍然看到同样的问题。此外,假设服务中没有任何内容,并且它有一个空的默认构造函数。或者,如果您想发挥想象力,假设它有一个打印“Hello world”的方法,同样是一个空的默认构造函数。换句话说,您的解决方案无法解决此问题。
  • 我明白了。而且您还使用 WebApi (2) 注册了您的 DependencyResolver?请注意,它是与常规 MVC 不同的注册。在那种情况下,我没有想法。
  • 我更新了一个使用 Owin 注册 Unity for WebAPi 的示例。
  • 是的,不幸的是,我已经尝试了您的每种注册方法以及其他一些涉及扩展解析器并注册您自己的方法,但没有成功。
  • 你能用新的注册更新你的代码吗?这是类似问题的另一个示例。 stackoverflow.com/questions/29611083/…
【解决方案2】:

DependencyResolver 设置为您在启动时创建的HttpConfiguration,而不是GlobalConfiguration.Configuration,并确保您的所有服务构造函数都是公开的,希望对您有所帮助

【讨论】:

    【解决方案3】:

    确保所有被注入的嵌套类型都被正确解析。即使嵌套类型解析不正确,您也会在控制器级别收到错误消息。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        我使用的是4.0.1 版本的Unity,在我的情况下,嵌套依赖项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 来装饰正确的构造函数,因为它被描述为 herehere - 但我什至在我的数据访问层中没有 Unity 引用(并且不要'不想)。

        请告诉我这种行为在以后的版本中是否有所改变。

        【讨论】:

          【解决方案6】:

          不幸的是,这些答案都不适合我。我已经按照此处描述的步骤使用了 smoksnes 提供的方法:https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection

          我的问题已通过使用特定于 web api 的统一包 (Unity.AspNet.WebApi) 而不是 Microsoft 指南中描述的通用 .net 包得到解决。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-06-20
            • 1970-01-01
            • 2023-04-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多