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

如何让Swashbuckle识别路由模板中未显式声明的参数类型?

解决Swagger未识别基控制器路由参数类型的问题

问题场景

我定义了基控制器TenantControllerBase,其预定义路由模板为api/s/{serviceId:int}/[controller],通过中间件提取serviceId并提供给所有继承该基类的控制器使用,无需在Action方法中显式声明该参数。但Swashbuckle生成的Swagger规范中,serviceId的类型被错误设置为string,而非路由模板指定的int。目前仅在Action方法签名中显式添加serviceId参数才能让Swagger识别其正确类型,希望找到无需添加参数的解决办法。

基控制器代码:

[Authorize]
[ApiController]
[Produces(MediaTypeNames.Application.Json)]
public abstract class TenantControllerBase : ControllerBase
{
    public const string DefaultRoute = "api/s/{serviceId:int}/[controller]";

    private readonly ITenantContext _tenantContext; // 中间件中提取serviceId的值

    protected int ServiceId => _tenantContext.ServiceId;

    protected TenantControllerBase(ITenantContext tenantContext)
    {
        _tenantContext = tenantContext ?? throw new ArgumentNullException(nameof(tenantContext));
    }
}

继承控制器示例:

[Route(DefaultRoute)]
public class SomeTenantController : TenantControllerBase
{
    public SomeTenantController(ITenantContext tenantContext) : base(tenantContext) { }

    [HttpGet("{type}")]
    public async Task<IActionResult> Get(string type, CancellationToken cancellationToken)
    {
        var serviceId = this.ServiceId;
        
        // 业务逻辑

        return Ok();
    }
}

解决方案

方法一:自定义Swagger操作过滤器修正参数类型

Swashbuckle默认从Action方法的参数列表解析路由参数类型,对于基控制器中定义但未在Action中声明的路由参数,需要手动解析路由模板的约束并修正Swagger的参数元数据。

  1. 创建自定义IOperationFilter:
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Text.RegularExpressions;

public class RouteParameterTypeFixFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var routeTemplate = context.ApiDescription.ActionDescriptor.AttributeRouteInfo?.Template;
        if (string.IsNullOrEmpty(routeTemplate)) return;

        // 匹配路由中的参数约束格式:{参数名:类型}
        var paramMatches = Regex.Matches(routeTemplate, @"{(\w+):(\w+)}");
        foreach (Match match in paramMatches)
        {
            var paramName = match.Groups[1].Value;
            var paramTypeConstraint = match.Groups[2].Value;

            // 找到Swagger中对应的路径参数
            var swaggerParam = operation.Parameters
                .FirstOrDefault(p => p.Name == paramName && p.In == ParameterLocation.Path);
            
            if (swaggerParam == null) continue;

            // 根据路由约束设置正确的Swagger类型和格式
            swaggerParam.Schema.Type = paramTypeConstraint switch
            {
                "int" => "integer",
                "long" => "integer",
                "bool" => "boolean",
                "decimal" => "number",
                _ => swaggerParam.Schema.Type
            };

            if (paramTypeConstraint is "int" or "long")
            {
                swaggerParam.Schema.Format = paramTypeConstraint == "int" ? "int32" : "int64";
            }
        }
    }
}
  1. 在Swagger配置中注册该过滤器:
builder.Services.AddSwaggerGen(c =>
{
    c.OperationFilter<RouteParameterTypeFixFilter>();
});

方法二:使用动态路由令牌转换器(.NET 5+)

通过自定义DynamicRouteValueTransformer,在路由解析阶段明确参数的类型,Swashbuckle会自动识别转换后的路由元数据,从而生成正确的参数类型定义。

  1. 创建路由转换器:
using Microsoft.AspNetCore.Routing;

public class TenantRouteTransformer : DynamicRouteValueTransformer
{
    public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
    {
        if (values.TryGetValue("serviceId", out var serviceIdObj) 
            && int.TryParse(serviceIdObj.ToString(), out int serviceId))
        {
            // 将字符串类型的serviceId转换为int,更新路由值字典
            values["serviceId"] = serviceId;
        }
        return new ValueTask<RouteValueDictionary>(values);
    }
}
  1. 注册路由转换器:
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers()
             .AddDynamicRouteValueTransformer<TenantRouteTransformer>();
});

效果验证

应用上述任一方案后,Swagger规范中serviceId的参数定义会自动修正为正确的类型:

{
  "name": "serviceId",
  "in": "path",
  "required": true,
  "style": "simple",
  "schema": {
    "type": "integer",
    "format": "int32"
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:44:54