.NET 6+ 中注册 OpenAPI 服务需在 Program.cs 使用最小托管模型:先 AddControllers(),再 AddEndpointsApiExplorer(),然后 AddSwaggerGen() 并配置文档、XML 注释及 JWT 安全定义。

Swashbuckle.AspNetCore 仍是当前(2026年).NET 6–8 项目中最稳定、最可控的 OpenAPI 文档方案;但如果你用的是 .NET 9+,优先考虑内置 AddOpenApi(),除非你明确需要 Swagger UI 的定制能力(比如自定义鉴权按钮、多文档切换、深度主题修改)。
如何在 Program.cs 中注册 OpenAPI 服务(.NET 6+)
不要照抄旧版 Startup.cs 写法。现代模板使用最小托管模型,所有配置集中在 Program.cs。
关键点:
-
AddEndpointsApiExplorer()必须在AddControllers()之后、AddSwaggerGen()之前调用,否则SwaggerGen扫不到控制器路由 -
AddSwaggerGen()默认不生成 XML 注释,要显示方法级说明,必须手动指定 XML 文件路径,并确保项目已启用 XML 文档生成功能(项目属性 → 生成 → 勾选“XML 文档文件”) - 若 API 含 JWT 鉴权,需显式添加
Bearer安全定义,否则 Swagger UI 不会出现 “Authorize” 按钮
示例片段:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "MyApi", Version = "v1" });
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
if (File.Exists(xmlPath)) c.IncludeXmlComments(xmlPath);
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme."
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});
为什么 UseSwagger() 和 UseSwaggerUI() 必须放在 app.UseRouting() 之后
顺序错会导致 404 或空白 UI 页面。中间件执行顺序是硬性约束:
-
UseRouting()负责解析请求路径并匹配端点 -
UseSwagger()依赖路由系统识别/swagger/v1/swagger.json这类路径,否则它根本收不到请求 -
UseSwaggerUI()是静态资源服务,也需路由前置才能正确挂载到/swagger
正确顺序(节选):
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger(); // ← 必须在 UseRouting 之后、UseEndpoints 之前
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyApi v1");
c.RoutePrefix = "swagger"; // 可选:把 UI 放在根路径下,即 /swagger
});
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
Swagger UI 访问 404 或 JSON 404 的常见原因
不是代码写错,而是环境或路径细节被忽略:
- 开发环境未启用:检查是否只在
if (env.IsDevelopment())块内调用UseSwagger(),而你正在用Production配置运行 - URL 手动输错:
/swagger是 UI 入口,/swagger/v1/swagger.json是文档地址,两者不能混用;注意大小写和斜杠结尾(/swagger/会 301 重定向,但某些代理会拦截) - HTTPS 重定向干扰:若项目启用了
app.UseHttpsRedirection(),但 Swagger UI 尝试用 HTTP 加载 JSON,浏览器会因混合内容阻止请求——此时需确保SwaggerEndpoint的 URL 协议与当前页面一致,或临时禁用 HTTPS 重定向做验证 - .NET 9+ 用户误装 Swashbuckle:内置 OpenAPI 不兼容
Swashbuckle.AspNetCore包,共存会引发服务注册冲突,报错如InvalidOperationException: Cannot resolve scoped service 'ISwaggerProvider'
XML 注释没显示?检查三个硬性条件
即使加了 IncludeXmlComments(),注释仍不出现,大概率卡在这三处:
- 项目文件中未开启 XML 输出:
<GenerateDocumentationFile>true</GenerateDocumentationFile>缺失,或值为false - XML 文件名不匹配:生成路径默认是
bin/Debug/net8.0/YourProject.xml,但代码里拼的是AppContext.BaseDirectory—— 如果你用dotnet run,该路径是项目根目录;如果用dotnet publish后运行,则是发布输出目录,二者不同 - 控制器方法上没写三斜杠注释:仅类注释(
/// <summary>)不够,每个[HttpGet]方法都得有独立注释块,且不能空行隔开
一个有效验证方式:
/// <summary> /// 获取用户列表 /// </summary> /// <returns>用户集合</returns> [HttpGet] public IEnumerable<User> Get() => _users;.NET 9 的内置 OpenAPI 支持虽省事,但移除了对
SwaggerEndpoint 动态 URL 注入、PreSerializeFilters 等底层控制能力——如果你的 API 部署在反向代理后(如 Nginx、Cloudflare),且真实 Host 与请求头不一致,Swashbuckle 仍是更可靠的选择。


















