You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 4.8 WebAPI手动实现DI报控制器无参构造错误排查

.NET Framework 4.8 原生DI实现控制器注入报错排查

问题场景

  • 项目为分层架构,WebAPI、BL、DAL各为独立项目且已定义对应接口,全部基于.NET Framework 4.8开发,首次尝试实现依赖注入
  • 未使用任何第三方IoC组件(如StructureMap、Autofac),仅需完成层间依赖注入
  • 参考公开技术方案配置后遇到运行报错,除Startup类和单个测试控制器外,其余代码未做修改
  • 接口调用返回错误:Make sure that the controller has a parameterless public constructor

现有实现代码

Startup.cs 配置代码

using TA.Services.WebAPI.Providers;

using System.Web.Http.Dependencies;
using Microsoft.Extensions.DependencyInjection;

using System.Linq;
using System.Web.Mvc;
using TA.Services.BL.BusinessLogic;
using TA.Services.BL.Interface;

[assembly: OwinStartup(typeof(TA.Services.WebAPI.Startup))]
namespace TA.Services.WebAPI
{
  public class Startup
  {
    public void Configuration(IAppBuilder app)
    {
      var services = new ServiceCollection();
      ConfigureServices(services);
      var resolver = new DefaultDependencyResolver(services.BuildServiceProvider());

      HttpConfiguration config = new HttpConfiguration();
      config.DependencyResolver = resolver;

      ConfigureOAuth(app);

      app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
      app.UseWebApi(config);
    }

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
          .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
          .Where(t => typeof(IController).IsAssignableFrom(t)
                      || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
    }

    public void ConfigureOAuth(IAppBuilder app)
    {
      OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
      {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
        Provider = new SimpleAuthorizationServerProvider()
      };

      // 令牌生成配置
      app.UseOAuthAuthorizationServer(OAuthServerOptions);
      app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    }
  }

  public class DefaultDependencyResolver : System.Web.Mvc.IDependencyResolver, System.Web.Http.Dependencies.IDependencyResolver
  {
    protected IServiceProvider serviceProvider;

    public DefaultDependencyResolver(IServiceProvider serviceProvider)
    {
      this.serviceProvider = serviceProvider;
    }

    public IDependencyScope BeginScope()
    {
      return new DefaultDependencyResolver(this.serviceProvider.CreateScope().ServiceProvider);
    }

    public void Dispose()
    {
    }

    public object GetService(Type serviceType)
    {
      return this.serviceProvider.GetService(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
      return this.serviceProvider.GetServices(serviceType);
    }
  }

  public static class ServiceProviderExtensions
  {
    public static IServiceCollection AddControllersAsServices(this IServiceCollection services,
        IEnumerable<Type> controllerTypes)
    {
      foreach (var type in controllerTypes)
      {
        services.AddTransient(type);
      }
      return services;
    }
  }
}

测试控制器修改

仅调整了控制器构造函数,注释原有无参构造,新增BL层接口注入参数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using TA.Services.BL.BusinessLogic;
using TA.Services.BL.Interface;
using TA.Services.DTO.DTO;
using TA.Services.WebAPI.Providers;

using Syncfusion.EJ2.Base;
using Newtonsoft.Json;
using TA.Services.WebAPI.Helpers;

namespace TA.Services.WebAPI.Controllers
{
  [WebApiConfig.CamelCaseControllerConfig]
  public class AuditsController : ApiController
  {
    private readonly IAuditsBL _auditsBL;
    
    /*
    public AuditsController()
    {
      _auditsBL = new AuditsBL();
    }
    */
    public AuditsController(IAuditsBL auditsBL)
    {
      _auditsBL = auditsBL;
    }
    // 其余接口方法省略
  }
}

已做排查调整

  • 在ConfigureServices方法中新增BL层服务注册,修改后代码如下:
public void ConfigureServices(IServiceCollection services)
{
  services.AddControllersAsServices(typeof(Startup).Assembly.GetExportedTypes()
      .Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
      .Where(t => typeof(IController).IsAssignableFrom(t)
                  || t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
  // 新增BL层服务注册
  services.AddSingleton<IAuditsBL, AuditsBL>();
}
  • 调试确认控制器和IAuditsBL服务均已正确注册到服务容器,但调用接口时仍返回无参构造函数缺失的错误。

待解答疑问

  1. 当前配置是否存在遗漏项?
  2. 已确认控制器注册到服务容器的前提下,是否还需要额外操作才能完成控制器与其依赖项的关联?

内容的提问来源于stack exchange,提问作者Hank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 18:09:22