如何在ASP.NET项目编译时为每个Controller生成独立Swagger.json文件
实现ASP.NET Core按Controller自动生成独立Swagger.json文件(构建阶段)
核心思路
无需硬编码Controller或文档名称,通过动态扫描项目内所有Controller,为每个Controller注册独立Swagger文档,再在构建阶段自动遍历所有文档生成对应swagger.json文件。以下是Swashbuckle和NSwag两种主流库的实现方案:
Swashbuckle 实现方案
1. 项目内动态配置多文档
在Program.cs中,自动扫描所有Controller并为每个Controller创建专属Swagger文档:
builder.Services.AddSwaggerGen(c => { // 扫描当前程序集内所有API控制器 var controllerTypes = typeof(Program).Assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && typeof(ControllerBase).IsAssignableFrom(t)); foreach (var controllerType in controllerTypes) { var controllerName = controllerType.Name.Replace("Controller", string.Empty); // 注册Controller对应的文档 c.SwaggerDoc(controllerName, new OpenApiInfo { Title = $"{controllerName} API", Version = "v1" }); // 过滤API,仅当前Controller的接口进入对应文档 c.DocInclusionPredicate((docName, apiDesc) => { if (!apiDesc.ActionDescriptor.RouteValues.TryGetValue("controller", out var controller)) return false; return controller.Equals(docName, StringComparison.OrdinalIgnoreCase); }); } }); // 启用Swagger端点 app.UseSwagger(); app.UseSwaggerUI(c => { // 动态注册所有文档的UI入口 var controllerNames = typeof(Program).Assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && typeof(ControllerBase).IsAssignableFrom(t)) .Select(t => t.Name.Replace("Controller", string.Empty)); foreach (var name in controllerNames) { c.SwaggerEndpoint($"/swagger/{name}/swagger.json", name); } });
2. 构建阶段自动生成所有Swagger.json
创建一个.NET控制台工具项目,用于在构建时启动测试服务器并批量生成文件:
using Microsoft.AspNetCore.Mvc.Testing; using System.Text.Json; var factory = new WebApplicationFactory<Program>(); var client = factory.CreateClient(); // 获取所有Controller对应的文档名称 var metadataResponse = await client.GetAsync("/swagger/v1/swagger.json"); metadataResponse.EnsureSuccessStatusCode(); var metadata = await metadataResponse.Content.ReadFromJsonAsync<JsonDocument>(); var docNames = metadata.RootElement.GetProperty("paths").EnumerateObject() .Select(p => p.Value.GetProperty("tags")[0].GetString()) .Distinct() .ToList(); // 逐个生成并保存Swagger.json到指定目录 var outputDir = Path.Combine(Directory.GetCurrentDirectory(), "../SwaggerOutput"); Directory.CreateDirectory(outputDir); foreach (var docName in docNames) { var swaggerResponse = await client.GetAsync($"/swagger/{docName}/swagger.json"); swaggerResponse.EnsureSuccessStatusCode(); var swaggerJson = await swaggerResponse.Content.ReadAsStringAsync(); var outputPath = Path.Combine(outputDir, $"{docName}.swagger.json"); await File.WriteAllTextAsync(outputPath, swaggerJson); }
最后在Web项目的.csproj中添加MSBuild目标,构建后自动执行该工具:
<Target Name="GenerateSwaggerPerController" AfterTargets="Build"> <Exec Command="dotnet run --project ../SwaggerGeneratorTool/SwaggerGeneratorTool.csproj" /> </Target>
NSwag 实现方案
1. 动态配置多文档
在Program.cs中为每个Controller注册独立的NSwag文档:
builder.Services.AddOpenApiDocument(settings => { settings.DocumentName = "All"; settings.Title = "All APIs"; }); // 扫描所有Controller并注册专属文档 var controllerTypes = typeof(Program).Assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && typeof(ControllerBase).IsAssignableFrom(t)); foreach (var controllerType in controllerTypes) { var controllerName = controllerType.Name.Replace("Controller", string.Empty); builder.Services.AddOpenApiDocument(settings => { settings.DocumentName = controllerName; settings.Title = $"{controllerName} API"; // 仅包含当前Controller的接口 settings.FilterControllers(c => c.Name.Equals(controllerType.Name, StringComparison.OrdinalIgnoreCase)); }); } // 启用NSwag端点 app.UseOpenApi(); app.UseSwaggerUi3();
2. 构建阶段批量生成
编写PowerShell脚本Generate-Swagger.ps1,动态获取文档并调用NSwag CLI生成文件:
# 启动Web应用(确保端口未被占用) $webAppProcess = Start-Process dotnet -ArgumentList "run --project YourWebApp.csproj" -PassThru Start-Sleep -Seconds 5 # 等待应用启动 # 获取所有文档名称 $response = Invoke-RestMethod -Uri "http://localhost:5000/swagger/v1/swagger.json" $docNames = $response.paths.PSObject.Properties.Value.tags | Select-Object -Unique # 创建输出目录 $outputDir = "../SwaggerOutput" if (-not (Test-Path $outputDir)) { New-Item -ItemType Directory -Path $outputDir | Out-Null } # 逐个生成Swagger.json foreach ($docName in $docNames) { nswag swagger2openapi /input:"http://localhost:5000/swagger/$docName/swagger.json" /output:"$outputDir/$docName.swagger.json" } # 停止Web应用进程 Stop-Process -Id $webAppProcess.Id
在Web项目的.csproj中添加构建后执行脚本的目标:
<Target Name="GenerateSwaggerPerController" AfterTargets="Build"> <Exec Command="powershell -File Generate-Swagger.ps1" /> </Target>
关键注意事项
- 使用测试服务器模式(Swashbuckle方案)比启动真实服务更稳定,避免端口冲突
- 扫描Controller时可添加额外过滤条件,排除非API控制器
- 确保构建环境中已安装NSwag CLI(若使用NSwag方案):
dotnet tool install -g NSwag.ConsoleCore
内容的提问来源于stack exchange,提问作者Vyrotek
相关产品推荐
相关产品推荐

