能否在ASP.NET WebAPI中使用外部DLL中的ApiController?
嘿,这个场景我之前在做模块化WebAPI的时候刚好碰到过,给你详细拆解一下~
ApiController 何时注册接收请求?
简单来说,控制器的注册是在WebAPI项目启动初始化阶段完成的,不同版本的ASP.NET细节略有不同:
- ASP.NET WebAPI(.NET Framework):启动时会执行
Global.asax里的Application_Start方法,当你调用GlobalConfiguration.Configure(WebApiConfig.Register)时,框架会扫描当前启动项目的程序集,找到所有继承自System.Web.Http.ApiController的类,把它们注册到控制器工厂和路由系统中。后续请求过来时,路由匹配成功后,框架就会通过这个注册列表找到对应的控制器实例处理请求。 - ASP.NET Core WebAPI(.NET Core/.NET 5+):在
Program.cs(老版本是Startup.cs)里调用builder.Services.AddControllers()时,框架会自动扫描当前项目的程序集,将符合条件的控制器(继承自Microsoft.AspNetCore.Mvc.ApiController)注册到DI容器,并关联到路由系统。请求进来后,路由中间件匹配到对应路由,就会从DI容器获取控制器实例来处理。
默认情况下,框架只会扫描启动项目自身的程序集,这就是为什么你的第二个项目里的控制器没被自动加载的原因。
如何强制加载外部项目的ApiController?
分两种框架版本给你说具体方案:
针对ASP.NET WebAPI(.NET Framework)
你需要自定义程序集解析器,告诉框架要额外扫描外部项目的程序集:
- 首先创建一个自定义的程序集解析器类:
public class CustomAssembliesResolver : DefaultAssembliesResolver { private readonly IEnumerable<Assembly> _extraAssemblies; public CustomAssembliesResolver(IEnumerable<Assembly> extraAssemblies) { _extraAssemblies = extraAssemblies; } public override ICollection<Assembly> GetAssemblies() { // 合并默认扫描的程序集和我们指定的外部程序集 var defaultAssemblies = base.GetAssemblies(); return defaultAssemblies.Union(_extraAssemblies).ToList(); } }
- 然后在
WebApiConfig.cs的Register方法里替换默认的解析器:
public static void Register(HttpConfiguration config) { // 路由配置等原有代码保持不变... // 加载外部项目的程序集(替换成你的外部项目程序集名称) var externalApiAssembly = Assembly.Load("YourExternalApiProjectName"); // 告诉WebAPI要扫描这个外部程序集 config.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver(new[] { Assembly.GetExecutingAssembly(), externalApiAssembly })); }
针对ASP.NET Core WebAPI(.NET Core/.NET 5+)
Core框架提供了更简洁的API,直接用AddApplicationPart就能搞定:
方法1:通过外部控制器类型获取程序集
如果能直接引用外部项目的类型,这种方式最可靠:
var builder = WebApplication.CreateBuilder(args); // 获取外部项目中任意一个控制器的程序集 var externalAssembly = typeof(YourExternalController).Assembly; // 添加控制器并指定要扫描的外部程序集 builder.Services.AddControllers() .AddApplicationPart(externalAssembly); // 后续的中间件配置等代码保持不变...
方法2:通过程序集名称加载
如果不想直接引用外部项目的类型,可以通过程序集名称加载:
var builder = WebApplication.CreateBuilder(args); // 替换成你的外部项目程序集名称 var externalAssembly = Assembly.Load("YourExternalApiProjectName"); builder.Services.AddControllers() .AddApplicationPart(externalAssembly); // 后续代码不变...
批量加载多个外部程序集
如果有多个外部项目的控制器要加载,可以批量处理:
var builder = WebApplication.CreateBuilder(args); var assembliesToScan = new[] { Assembly.Load("ExternalApiProject1"), Assembly.Load("ExternalApiProject2") }; var mvcBuilder = builder.Services.AddControllers(); foreach (var assembly in assembliesToScan) { mvcBuilder.AddApplicationPart(assembly); } // 后续代码不变...
小提示
- 不管哪种框架,都要确保外部项目的控制器继承了对应的
ApiController基类(Framework是System.Web.Http.ApiController,Core是Microsoft.AspNetCore.Mvc.ApiController),而且控制器类名默认要以Controller结尾(这个约定可以改,但没必要额外折腾)。 - Core版本下,要保证外部项目的目标框架和主项目兼容,比如主项目是.NET 6,外部项目不能是.NET Framework 4.x系列。
内容的提问来源于stack exchange,提问作者LuizLoyola
相关产品推荐
相关产品推荐

