56 lines
2.1 KiB
C#
56 lines
2.1 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
|
|
namespace MAX.Framework.Conventions;
|
|
|
|
/// <summary>为 API 控制器的属性路由统一添加 api 前缀,已含前缀的路由保持不变。</summary>
|
|
public sealed class ApiRoutePrefixConvention : IApplicationModelConvention
|
|
{
|
|
public void Apply(ApplicationModel application)
|
|
{
|
|
foreach (var controller in application.Controllers)
|
|
{
|
|
if (!controller.Attributes.OfType<IApiBehaviorMetadata>().Any()
|
|
&& !controller.ControllerType.Assembly.IsDefined(typeof(ApiControllerAttribute), true))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var hasControllerRoute = controller.Selectors.Any(selector => selector.AttributeRouteModel != null);
|
|
foreach (var selector in controller.Selectors)
|
|
{
|
|
if (selector.AttributeRouteModel is { } route)
|
|
{
|
|
AddPrefix(route);
|
|
}
|
|
}
|
|
|
|
foreach (var action in controller.Actions)
|
|
foreach (var selector in action.Selectors)
|
|
{
|
|
// 绝对动作路由会覆盖控制器路由,因此需要单独添加前缀。
|
|
if (selector.AttributeRouteModel is { } route
|
|
&& (!hasControllerRoute || route.IsAbsoluteTemplate))
|
|
{
|
|
AddPrefix(route);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void AddPrefix(AttributeRouteModel route)
|
|
{
|
|
var template = route.Template ?? "";
|
|
var absolute = route.IsAbsoluteTemplate;
|
|
template = template.StartsWith("~/", StringComparison.Ordinal) ? template[2..] : template.TrimStart('/');
|
|
if (!template.Equals("api", StringComparison.OrdinalIgnoreCase)
|
|
&& !template.StartsWith("api/", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
template = string.IsNullOrEmpty(template) ? "api" : $"api/{template}";
|
|
}
|
|
|
|
route.Template = absolute ? $"~/{template}" : template;
|
|
}
|
|
}
|