Azure DevOps中ASP.NET Core Web API的Swagger CI生成问题
在Azure DevOps构建阶段无依赖生成Swagger的解决方案
当前使用Swashbuckle.AspNetCore.Cli生成Swagger文档时,CLI会启动整个Web应用,触发配置文件加载(如appsettings.json)甚至数据库连接逻辑,在CI环境中容易引发依赖缺失问题。以下是几种可行的解决思路:
1. 调整配置加载逻辑,适配Swagger CLI场景
在项目的Program.cs(或Main方法)中,通过命令行参数识别Swagger CLI调用场景,允许配置文件可选,避免因缺失配置导致启动失败:
var isSwaggerCli = args.Any(arg => arg.Contains("swagger", StringComparison.OrdinalIgnoreCase)); IConfiguration Configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) // Swagger CLI调用时,允许appsettings.json不存在 .AddJsonFile("appsettings.json", optional: isSwaggerCli, reloadOnChange: true) .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true) .AddEnvironmentVariables() .Build();
2. 跳过非必要服务的注册
生成Swagger仅需要控制器和模型的元数据,无需初始化数据库、第三方服务等依赖。在服务注册阶段判断Swagger CLI场景,跳过这些非必要服务:
var builder = WebApplication.CreateBuilder(args); var isSwaggerCli = args.Any(arg => arg.Contains("swagger", StringComparison.OrdinalIgnoreCase)); // 仅在非Swagger场景下注册数据库等依赖服务 if (!isSwaggerCli) { builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); } // 始终注册Swagger生成所需服务 builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Api", Version = "v1" }); }); var app = builder.Build(); // 非Swagger场景下才配置业务相关中间件 if (!isSwaggerCli) { app.UseHttpsRedirection(); app.UseAuthorization(); } // 保留Swagger中间件以支持CLI生成 app.UseSwagger(); app.Run();
3. 脱离Web应用,直接通过代码生成Swagger文档
创建一个独立的控制台项目,利用Swashbuckle.AspNetCore.SwaggerGen从Api程序集提取元数据生成文档,无需启动Web应用:
步骤:
- 在解决方案中添加一个.NET控制台项目
- 安装NuGet包:
Swashbuckle.AspNetCore.SwaggerGen、Microsoft.AspNetCore.Mvc.Core - 编写生成代码:
using Microsoft.AspNetCore.Mvc.ApiExplorer; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; using System.Text.Json; using System.Reflection; // 替换为你的Api项目程序集路径 var apiAssemblyPath = Path.Combine(Environment.GetEnvironmentVariable("SYSTEM_DEFAULTWORKINGDIRECTORY") ?? "", "src/Api/bin/Release/net8.0/Api.dll"); var apiAssembly = Assembly.LoadFrom(apiAssemblyPath); var services = new ServiceCollection(); // 添加Api程序集作为应用部件 services.AddControllers() .AddApplicationPart(apiAssembly); // 配置Swagger生成 services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Api", Version = "v1" }); // 若Api使用了XML注释,可添加以下配置 // var xmlFile = $"{apiAssembly.GetName().Name}.xml"; // var xmlPath = Path.Combine(Path.GetDirectoryName(apiAssemblyPath) ?? "", xmlFile); // c.IncludeXmlComments(xmlPath); }); var serviceProvider = services.BuildServiceProvider(); var apiDescriptionProvider = serviceProvider.GetRequiredService<IApiDescriptionGroupCollectionProvider>(); var swaggerGenerator = serviceProvider.GetRequiredService<ISwaggerProvider>(); // 生成Swagger文档 var swaggerDoc = swaggerGenerator.GetSwagger("v1"); // 保存到构建产物目录 var outputPath = Path.Combine(Environment.GetEnvironmentVariable("BUILD_ARTIFACTSTAGINGDIRECTORY") ?? "./", "swagger.json"); using var fs = new FileStream(outputPath, FileMode.Create); await JsonSerializer.SerializeAsync(fs, swaggerDoc, new JsonSerializerOptions { WriteIndented = true });
- 在Azure DevOps构建任务中,先编译该控制台项目,再运行生成命令,替换原有的CmdLine任务。
4. (备选)确保CI环境中存在必要配置文件
如果必须保留原有启动逻辑,可在Azure DevOps任务中添加文件复制步骤,将appsettings.json(或一个仅包含空配置的版本)复制到工作目录:
- task: CopyFiles@2 displayName: 'Copy Appsettings' inputs: SourceFolder: 'src/Api' Contents: 'appsettings.json' TargetFolder: '$(System.DefaultWorkingDirectory)/Api'
内容的提问来源于stack exchange,提问作者dna
相关产品推荐
相关产品推荐

