如何让Swagger JSON显示CatchAll路由参数的星号?
让Swashbuckle.AspNetCore生成的Swagger保留CatchAll路由星号
问题场景
我有个控制器方法,路由参数用了CatchAll星号{*routeAddress},用来接收包含斜杠/的参数值,代码如下:
[HttpGet] [Route("Check/{*routeAddress}")] public IActionResult Check([RegularExpression(@"^[a-zA-Z0-9.\/?=&-]*$", ErrorMessage = "Characters are not allowed."), StringLength(200)] string routeAddress) { ... }
但用Swashbuckle.AspNetCore生成Swagger JSON时,路径里的参数没带星号,示例如下:
"/MyControllerName/Check/{routeAddress}": { "get": { "tags": [ "MyControllerName" ], "parameters": [ { "name": "routeAddress", "in": "path", "required": true, "schema": { "maxLength": 200, "minLength": 0, "pattern": "^[a-zA-Z0-9.\\/?=&-]*$", "type": "string" } } ], "responses": { "200": { "description": "Success" } } } }
把这个Swagger部署到F5后,因为缺少星号,F5拒绝接收含/的参数请求,得想办法让Swagger JSON里显示这个星号。
解决方法
1. 自定义Swagger文档过滤器
写一个实现IDocumentFilter的类,遍历Swagger文档的所有路径,识别出CatchAll参数,给对应的占位符加上星号:
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Linq; public class CatchAllRouteDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { var updatedPaths = new OpenApiPaths(); foreach (var pathEntry in swaggerDoc.Paths) { var currentPath = pathEntry.Key; var pathOperations = pathEntry.Value; // 找到当前路径对应的API描述和Action信息 var apiDesc = context.ApiDescriptions.FirstOrDefault(api => api.RelativePath == currentPath.TrimStart('/')); if (apiDesc?.ActionDescriptor != null) { // 筛选出CatchAll类型的路由参数 var catchAllParams = apiDesc.ActionDescriptor.Parameters .Where(p => p.RouteInfo?.IsCatchAll == true); foreach (var param in catchAllParams) { // 替换路径中的参数占位符,加上星号前缀 currentPath = currentPath.Replace($"{{{param.Name}}}", $"{{*{param.Name}}}"); } } updatedPaths.Add(currentPath, pathOperations); } swaggerDoc.Paths = updatedPaths; } }
2. 注册过滤器到Swagger生成器
在项目的配置文件(比如Program.cs)里,配置SwaggerGen时添加这个自定义过滤器:
builder.Services.AddSwaggerGen(c => { // 注册CatchAll路由过滤器 c.DocumentFilter<CatchAllRouteDocumentFilter>(); // 其他Swagger相关配置(比如文档信息、注释等) });
3. 验证结果
重新启动项目生成Swagger JSON,对应的路径会变成"/MyControllerName/Check/{*routeAddress}",这样部署到F5后就能正常接收含/的参数请求了。
内容的提问来源于stack exchange,提问作者banana
相关产品推荐
相关产品推荐

