You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 09:22:49