如何通过自定义IApplicationModelProvider注册带多段路由的泛型控制器?
自定义IApplicationModelProvider注册多段路由的泛型控制器
核心思路
通过实现IApplicationModelProvider动态生成泛型控制器的具体实例模型,将自定义的多段路由前缀绑定到对应实体类型的泛型控制器上,同时让ASP.NET的默认模型处理逻辑自动识别控制器的Action、属性、过滤器等。
步骤1:定义泛型控制器基类
先编写包含通用业务逻辑的泛型控制器,确保Action、过滤器等特性标记正确:
[ApiController] public class GenericController<T> : ControllerBase { [HttpGet] public IActionResult GetAll() { return Ok($"返回所有{typeof(T).Name}数据"); } [HttpGet("{id}")] public IActionResult GetById(int id) { return Ok($"返回ID为{id}的{typeof(T).Name}数据"); } [HttpPost] [Authorize] public IActionResult Create([FromBody] T model) { return CreatedAtAction(nameof(GetById), new { id = 1 }, model); } }
步骤2:实现自定义IApplicationModelProvider
该类负责动态注册泛型控制器实例,并绑定多段路由:
using Microsoft.AspNetCore.Mvc.ApplicationModels; using System.Reflection; public class GenericControllerModelProvider : IApplicationModelProvider { // 设置优先级低于默认Provider(默认Order为0),确保默认逻辑能处理我们添加的控制器 public int Order => -1000; public void OnProvidersExecuting(ApplicationModelProviderContext context) { // 配置实体类型与对应路由段的映射 var controllerMappings = new Dictionary<Type, string[]> { { typeof(Person), new[] { "Person" } }, { typeof(Employee), new[] { "hr", "Employee" } }, { typeof(Department), new[] { "company", "admin", "Department" } } // 可扩展更多实体和多段路由 }; foreach (var mapping in controllerMappings) { var entityType = mapping.Key; var routeSegments = mapping.Value; // 创建泛型控制器的具体类型 var genericControllerType = typeof(GenericController<>).MakeGenericType(entityType); var controllerTypeInfo = genericControllerType.GetTypeInfo(); // 构建控制器模型 var controllerModel = new ControllerModel(controllerTypeInfo, Array.Empty<object>()); // 设置控制器名称(用于路由匹配) controllerModel.ControllerName = routeSegments.Last(); // 添加多段路由前缀 var routeTemplate = string.Join("/", routeSegments); controllerModel.Selectors.Add(new SelectorModel { AttributeRouteModel = new AttributeRouteModel(new RouteAttribute(routeTemplate)) }); // 将控制器模型加入应用模型,后续默认Provider会自动解析Action、过滤器、属性等 context.Result.Controllers.Add(controllerModel); } } public void OnProvidersExecuted(ApplicationModelProviderContext context) { // 可在此对已生成的模型做后续调整(如修改路由约束、添加全局过滤器等) } }
步骤3:注册自定义Provider
在Program.cs中将自定义Provider添加到服务集合:
var builder = WebApplication.CreateBuilder(args); // 添加控制器服务,并注册自定义模型提供者 builder.Services.AddControllers(options => { options.ModelMetadataDetailsProviders.Add(new GenericControllerModelProvider()); }); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
关键注意事项
- 泛型控制器基类上的特性(如
[ApiController]、[Authorize])会被自动继承,默认模型处理逻辑会识别并应用这些特性的行为。 - 路由段的最后一段需与控制器名称一致,确保ASP.NET路由系统能正确匹配到对应的控制器实例。
- 如果需要自定义路由约束或额外路由值,可在
SelectorModel中扩展RouteValueDictionary或添加RouteConstraintModel。
内容的提问来源于stack exchange,提问作者Goran Petrović
相关产品推荐
相关产品推荐

