ASP.NET Web API+Swagger多视图控制器权限控制可行性咨询
完全可以实现!我之前在项目里做过类似的需求,通过Swagger的多文档配置和筛选机制就能搞定,具体步骤如下:
实现Swagger多视图(按控制器分组)的步骤
1. 确保已安装Swashbuckle.AspNetCore包
如果你还没装,用NuGet安装Swashbuckle.AspNetCore(包含Swagger生成和UI组件)。
2. 配置多个Swagger文档
在Program.cs(.NET 6+)或者Startup.cs的ConfigureServices方法里,添加多个Swagger文档定义,每个文档对应一个视图版本:
builder.Services.AddSwaggerGen(c => { // v1:显示所有控制器 c.SwaggerDoc("v1", new OpenApiInfo { Title = "All APIs", Version = "v1", Description = "包含所有5个控制器的API文档" }); // v2:仅显示1个控制器(比如Controller3) c.SwaggerDoc("v2", new OpenApiInfo { Title = "Single Controller API", Version = "v2", Description = "仅包含Controller3的API文档" }); // v3:仅显示2个控制器(比如Controller4和Controller5) c.SwaggerDoc("v3", new OpenApiInfo { Title = "Two Controllers API", Version = "v3", Description = "包含Controller4和Controller5的API文档" }); });
3. 添加文档筛选逻辑
有两种方式实现控制器的筛选,选一种适合你的:
方式一:基于控制器分组特性(推荐)
给目标控制器添加[ApiExplorerSettings]特性指定分组,然后配置Swagger只包含对应分组的API:
首先给控制器加特性:
// 所有控制器都默认属于v1(不需要额外加,因为v1会包含所有) [ApiController] [Route("api/[controller]")] public class Controller1 : ControllerBase { /* 动作方法 */ } // Controller3同时属于v1和v2 [ApiController] [Route("api/[controller]")] [ApiExplorerSettings(GroupName = "v2")] public class Controller3 : ControllerBase { /* 动作方法 */ } // Controller4和Controller5同时属于v1和v3 [ApiController] [Route("api/[controller]")] [ApiExplorerSettings(GroupName = "v3")] public class Controller4 : ControllerBase { /* 动作方法 */ } [ApiController] [Route("api/[controller]")] [ApiExplorerSettings(GroupName = "v3")] public class Controller5 : ControllerBase { /* 动作方法 */ }
然后在AddSwaggerGen里添加DocInclusionPredicate来筛选每个文档包含的API:
builder.Services.AddSwaggerGen(c => { // ... 之前的SwaggerDoc配置 ... c.DocInclusionPredicate((docName, apiDesc) => { // 获取当前API所属的控制器分组 var controllerGroupName = apiDesc.ActionDescriptor.EndpointMetadata .OfType<ApiExplorerSettingsAttribute>() .FirstOrDefault()?.GroupName; switch (docName) { case "v1": // v1包含所有API,不管分组 return true; case "v2": // v2只包含分组为v2的API return controllerGroupName == "v2"; case "v3": // v3只包含分组为v3的API return controllerGroupName == "v3"; default: return false; } }); });
方式二:基于路径筛选(适合不想改控制器代码的情况)
创建一个IDocumentFilter实现类,根据文档版本过滤API路径:
public class SwaggerControllerFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { switch (swaggerDoc.Info.Version) { case "v2": // 只保留Controller3的API(假设路由是/api/controller3/...) swaggerDoc.Paths = swaggerDoc.Paths .Where(p => p.Key.StartsWith("/api/controller3/")) .ToDictionary(p => p.Key, p => p.Value); break; case "v3": // 保留Controller4和Controller5的API swaggerDoc.Paths = swaggerDoc.Paths .Where(p => p.Key.StartsWith("/api/controller4/") || p.Key.StartsWith("/api/controller5/")) .ToDictionary(p => p.Key, p => p.Value); break; // v1保留所有,无需处理 } } }
然后在AddSwaggerGen里注册这个过滤器:
builder.Services.AddSwaggerGen(c => { // ... 之前的SwaggerDoc配置 ... c.DocumentFilter<SwaggerControllerFilter>(); });
4. 配置Swagger UI并实现自定义URL跳转
默认Swagger UI是通过下拉菜单切换文档的,为了实现/swagger/v1、/swagger/v2这样的直接访问URL,我们可以添加重定向中间件:
在Program.cs的Configure(或app.Run之前)添加:
app.UseSwagger(); app.UseSwaggerUI(c => { // 注册所有Swagger文档端点 c.SwaggerEndpoint("/swagger/v1/swagger.json", "All APIs v1"); c.SwaggerEndpoint("/swagger/v2/swagger.json", "Single Controller v2"); c.SwaggerEndpoint("/swagger/v3/swagger.json", "Two Controllers v3"); // 设置默认UI路径 c.RoutePrefix = "swagger"; }); // 添加自定义URL重定向,让用户可以直接访问/swagger/v1等路径 app.MapGet("/swagger/v1", context => { context.Response.Redirect("/swagger/index.html?url=/swagger/v1/swagger.json"); return Task.CompletedTask; }); app.MapGet("/swagger/v2", context => { context.Response.Redirect("/swagger/index.html?url=/swagger/v2/swagger.json"); return Task.CompletedTask; }); app.MapGet("/swagger/v3", context => { context.Response.Redirect("/swagger/index.html?url=/swagger/v3/swagger.json"); return Task.CompletedTask; });
5. 测试验证
启动项目后:
- 访问
http://localhost:5000/swagger/v1:显示所有5个控制器的API - 访问
http://localhost:5000/swagger/v2:仅显示你指定的1个控制器 - 访问
http://localhost:5000/swagger/v3:仅显示你指定的2个控制器
这样就完美实现了按需求分享不同Swagger视图的目的!
内容的提问来源于stack exchange,提问作者SharpCoder
相关产品推荐
相关产品推荐

