.NET7 Web API如何在OpenAPI规范中保留集合资源URI的尾斜杠?
解决Swashbuckle.AspNetCore生成OpenAPI时保留集合资源URI尾斜杠的问题
Swashbuckle.AspNetCore默认会自动移除OpenAPI规范中路径末尾的斜杠,这就是为什么你在控制器Route属性里加了尾斜杠,生成的文档里却没显示的原因。要实现仅在OpenAPI文档中保留集合资源的尾斜杠,同时不影响API请求处理,可以通过自定义文档过滤器来修改生成的规范内容。
方案一:全局识别原始路由模板保留尾斜杠
创建一个实现IDocumentFilter的过滤器类,通过读取控制器的原始路由模板,判断是否需要为路径添加尾斜杠:
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; public class PreserveTrailingSlashDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { var updatedPaths = new OpenApiPaths(); foreach (var pathEntry in swaggerDoc.Paths) { var apiDesc = context.ApiDescriptions.FirstOrDefault( desc => desc.RelativePath == pathEntry.Key.TrimStart('/')); string newPathKey = pathEntry.Key; // 检查原始路由模板是否以斜杠结尾,且当前路径未带斜杠 if (apiDesc?.ActionDescriptor.AttributeRouteInfo?.Template != null && apiDesc.ActionDescriptor.AttributeRouteInfo.Template.EndsWith("/") && !newPathKey.EndsWith("/")) { newPathKey = $"{newPathKey}/"; } updatedPaths.Add(newPathKey, pathEntry.Value); } swaggerDoc.Paths = updatedPaths; } }
然后在Program.cs中注册这个过滤器:
builder.Services.AddSwaggerGen(c => { // 你的Swagger基础配置(如API信息、版本控制等) c.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API", Version = "v1" }); // 注册自定义文档过滤器 c.DocumentFilter<PreserveTrailingSlashDocumentFilter>(); });
方案二:通过自定义属性精准控制集合资源
如果只想给特定的集合控制器/Action保留尾斜杠,可以先定义一个标记属性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class PreserveTrailingSlashAttribute : Attribute { }
然后在需要的控制器上添加该属性:
[ApiController] [Route("api/v{version:apiVersion}/schools/")] [PreserveTrailingSlash] // 添加标记属性 public class SchoolsController : ControllerBase { // GET: api/v1/schools/ [HttpGet] public IActionResult GetSchools() => Ok(); // POST: api/v1/schools/ [HttpPost] public IActionResult CreateSchool(SchoolDto dto) => Created(); }
接着修改过滤器类,识别这个标记属性并处理路径:
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; public class PreserveTrailingSlashDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { var updatedPaths = new OpenApiPaths(); // 先处理带标记属性的路径 foreach (var apiDesc in context.ApiDescriptions) { var hasPreserveAttr = apiDesc.ActionDescriptor.ControllerTypeInfo .GetCustomAttributes<PreserveTrailingSlashAttribute>().Any() || apiDesc.ActionDescriptor.MethodInfo .GetCustomAttributes<PreserveTrailingSlashAttribute>().Any(); if (hasPreserveAttr) { string originalPath = "/" + apiDesc.RelativePath; string newPath = originalPath.EndsWith("/") ? originalPath : $"{originalPath}/"; if (swaggerDoc.Paths.TryGetValue(originalPath, out var pathItem)) { updatedPaths.Add(newPath, pathItem); swaggerDoc.Paths.Remove(originalPath); } } } // 保留其他未标记的路径 foreach (var pathEntry in swaggerDoc.Paths) { if (!updatedPaths.ContainsKey(pathEntry.Key)) { updatedPaths.Add(pathEntry.Key, pathEntry.Value); } } swaggerDoc.Paths = updatedPaths; } }
同样在Program.cs中注册这个过滤器即可。
注意事项
- .NET Web API默认会自动兼容带或不带尾斜杠的请求,无需额外配置严格路由校验,符合你的需求。
- 上述两种方案都会让Swagger UI中的测试链接自动带上尾斜杠,保证API使用者看到的规范符合要求。
内容的提问来源于stack exchange,提问作者exploring.cheerily.impresses
相关产品推荐
相关产品推荐

