.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服务均已正确注册到服务容器,但调用接口时仍返回无参构造函数缺失的错误。
待解答疑问
- 当前配置是否存在遗漏项?
- 已确认控制器注册到服务容器的前提下,是否还需要额外操作才能完成控制器与其依赖项的关联?
内容的提问来源于stack exchange,提问作者Hank
相关产品推荐
相关产品推荐

