如何在单个C# ASP.NET Core应用中为私有与公有API部署独立路径的Swagger UI
在ASP.NET Core中为公有/私有API部署独立的Swagger UI
我刚好做过一模一样的需求,你现在的问题主要是原来的配置把两个文档塞到了同一个Swagger UI里,只要调整两处配置就能实现完全独立的两个UI,具体步骤如下:
第一步:修复Swagger文档生成的注册逻辑
你之前两次调用AddSwaggerGen会覆盖掉第一次的配置,正确的做法是在同一个AddSwaggerGen里注册两个文档,同时让你的过滤器能区分处理对应的文档。
首先修改你的过滤器(以PublicAPISwaggerFilter为例),让它只处理公有文档:
public class PublicAPISwaggerFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { // 只处理标题为"Public API"的文档 if (swaggerDoc.Info.Title != "Public API") return; // 遍历所有API路径,移除私有API foreach (var pathEntry in swaggerDoc.Paths.ToList()) { var apiDesc = context.ApiDescriptions.FirstOrDefault(d => d.RelativePath.Equals(pathEntry.Key.TrimStart('/'), StringComparison.OrdinalIgnoreCase)); // 这里根据你标记私有API的方式判断,比如检查是否有[PrivateApi]特性 if (apiDesc?.ControllerAttributes().Any(a => a is PrivateApiAttribute) == true || apiDesc?.ActionAttributes().Any(a => a is PrivateApiAttribute) == true) { swaggerDoc.Paths.Remove(pathEntry.Key); } } } }
对应的PrivateApiSwaggerFilter也做类似调整,只处理标题为"Private API"的文档,移除公有API。
然后在ConfigureServices里合并Swagger的注册:
public void ConfigureServices(IServiceCollection services) { ... services.AddSwaggerGen(c => { // 注册公有API文档 c.SwaggerDoc("v0.1_public", new OpenApiInfo { Title = "Public API", Version = "v0.1" }); // 注册私有API文档 c.SwaggerDoc("v0.1_private", new OpenApiInfo { Title = "Private API", Version = "v0.1" }); // 添加两个过滤器,它们会自动处理对应文档 c.DocumentFilter<PublicAPISwaggerFilter>(); c.DocumentFilter<PrivateApiSwaggerFilter>(); }); ... }
第二步:配置两个独立的Swagger UI
在Configure方法里,你需要多次调用UseSwaggerUI,每个指定不同的路由前缀,并且只加载对应的文档:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { ... // 先启用Swagger JSON文档服务(这一步只需要调用一次) app.UseSwagger(); // 配置公有API的Swagger UI,访问路径:/public/swagger app.UseSwaggerUI(c => { c.RoutePrefix = "public/swagger"; // 只加载公有API的JSON文档 c.SwaggerEndpoint("/swagger/v0.1_public/swagger.json", "Public API v0.1"); // 可选:隐藏Models面板,如果你的API不需要展示模型 c.DefaultModelsExpandDepth(-1); }); // 配置私有API的Swagger UI,访问路径:/private/swagger app.UseSwaggerUI(c => { c.RoutePrefix = "private/swagger"; // 只加载私有API的JSON文档 c.SwaggerEndpoint("/swagger/v0.1_private/swagger.json", "Private API v0.1"); }); ... }
补充:API标记建议
为了更清晰地区分公有和私有API,建议自定义两个特性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class PublicApiAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class PrivateApiAttribute : Attribute { }
然后在你的控制器/Action上标记:
[ApiController] [Route("api/public/[controller]")] [PublicApi] public class PublicDataController : ControllerBase { // 这里的方法都会被归为公有API } [ApiController] [Route("api/private/[controller]")] [PrivateApi] public class InternalDataController : ControllerBase { // 这里的方法都会被归为私有API }
这样你的过滤器逻辑会更可靠,不会误过滤API。
现在启动应用测试:
- 访问
https://localhost:port/public/swagger:只能看到公有API的文档,没有下拉菜单 - 访问
https://localhost:port/private/swagger:只能看到私有API的文档,完全独立
内容的提问来源于stack exchange,提问作者Aksim
相关产品推荐
相关产品推荐

