dotnet-openapi
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesedotnet-openapi
dotnet-openapi
OpenAPI/Swagger integration for ASP.NET Core. Microsoft.AspNetCore.OpenApi is the recommended first-party approach for .NET 9+ and is the default in new project templates. Swashbuckle is no longer actively maintained; existing projects using Swashbuckle should plan migration. NSwag remains an alternative for client generation and advanced scenarios.
Out of scope: Minimal API endpoint patterns (route groups, filters, TypedResults) -- see [skill:dotnet-minimal-apis]. API versioning strategies -- see [skill:dotnet-api-versioning]. Authentication and authorization -- see [skill:dotnet-api-security].
Cross-references: [skill:dotnet-minimal-apis] for endpoint patterns that generate OpenAPI metadata, [skill:dotnet-api-versioning] for versioned OpenAPI documents.
适用于ASP.NET Core的OpenAPI/Swagger集成方案。Microsoft.AspNetCore.OpenApi是.NET 9+推荐使用的官方方案,也是新项目模板中的默认选项。Swashbuckle已不再积极维护;使用Swashbuckle的现有项目应规划迁移工作。NSwag仍是客户端生成和高级场景下的替代方案。
超出范围内容: 极简API端点模式(路由组、过滤器、TypedResults)——请查看[skill:dotnet-minimal-apis]。API版本控制策略——请查看[skill:dotnet-api-versioning]。身份认证与授权——请查看[skill:dotnet-api-security]。
交叉引用:[skill:dotnet-minimal-apis] 提供生成OpenAPI元数据的端点模式,[skill:dotnet-api-versioning] 提供版本化OpenAPI文档相关内容。
Microsoft.AspNetCore.OpenApi (Recommended)
Microsoft.AspNetCore.OpenApi(推荐方案)
Microsoft.AspNetCore.OpenApi is the first-party OpenAPI package for ASP.NET Core 9+ and is included by default in new project templates. .NET 10 adds OpenAPI 3.1 support with JSON Schema draft 2020-12 compliance.
Microsoft.AspNetCore.OpenApi是ASP.NET Core 9+的官方OpenAPI包,默认包含在新项目模板中。.NET 10新增了对OpenAPI 3.1的支持,兼容JSON Schema draft 2020-12规范。
Basic Setup
基础配置
csharp
// Microsoft.AspNetCore.OpenApi -- included by default in .NET 9+ project templates
// If not present, add: <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.*" />
// Version must match the project's target framework major version
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi(); // Serves /openapi/v1.json
}csharp
// Microsoft.AspNetCore.OpenApi —— .NET 9+项目模板默认包含
// 若未添加,可引入:<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.*" />
// 版本必须与项目目标框架的主版本号匹配
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi(); // 提供 /openapi/v1.json 接口
}Multiple Documents
多文档生成
Generate separate OpenAPI documents per API version or functional group:
csharp
builder.Services.AddOpenApi("v1", options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_0;
});
builder.Services.AddOpenApi("v2", options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});
var app = builder.Build();
app.MapOpenApi(); // Serves /openapi/v1.json and /openapi/v2.json可为不同API版本或功能组生成独立的OpenAPI文档:
csharp
builder.Services.AddOpenApi("v1", options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_0;
});
builder.Services.AddOpenApi("v2", options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});
var app = builder.Build();
app.MapOpenApi(); // 提供 /openapi/v1.json 和 /openapi/v2.json 接口Document Transformers
文档转换器
Document transformers modify the generated OpenAPI document after it is built. Use them to add server information, security schemes, or custom metadata.
文档转换器可在OpenAPI文档生成后对其进行修改。可用于添加服务器信息、安全方案或自定义元数据。
IOpenApiDocumentTransformer
IOpenApiDocumentTransformer
csharp
public sealed class SecuritySchemeTransformer : IOpenApiDocumentTransformer
{
public Task TransformAsync(
OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken cancellationToken)
{
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "JWT Bearer token authentication"
};
document.SecurityRequirements.Add(new OpenApiSecurityRequirement
{
[new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
}] = Array.Empty<string>()
});
return Task.CompletedTask;
}
}
// Register the transformer
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer<SecuritySchemeTransformer>();
});csharp
public sealed class SecuritySchemeTransformer : IOpenApiDocumentTransformer
{
public Task TransformAsync(
OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken cancellationToken)
{
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "JWT Bearer token authentication"
};
document.SecurityRequirements.Add(new OpenApiSecurityRequirement
{
[new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
}] = Array.Empty<string>()
});
return Task.CompletedTask;
}
}
// 注册转换器
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer<SecuritySchemeTransformer>();
});Lambda Document Transformers
Lambda文档转换器
For simple transformations, use the lambda overload:
csharp
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, context, ct) =>
{
document.Info = new OpenApiInfo
{
Title = "Products API",
Version = "v1",
Description = "Product catalog management API",
Contact = new OpenApiContact
{
Name = "API Support",
Email = "api-support@example.com"
}
};
return Task.CompletedTask;
});
});对于简单的转换操作,可使用Lambda重载:
csharp
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, context, ct) =>
{
document.Info = new OpenApiInfo
{
Title = "Products API",
Version = "v1",
Description = "Product catalog management API",
Contact = new OpenApiContact
{
Name = "API Support",
Email = "api-support@example.com"
}
};
return Task.CompletedTask;
});
});Operation Transformers
操作转换器
Operation transformers modify individual operations (endpoints) in the OpenAPI document. Use them to add per-operation metadata, examples, or conditional logic.
csharp
public sealed class DeprecationTransformer : IOpenApiOperationTransformer
{
public Task TransformAsync(
OpenApiOperation operation,
OpenApiOperationTransformerContext context,
CancellationToken cancellationToken)
{
var deprecatedAttr = context.Description.ActionDescriptor
.EndpointMetadata
.OfType<ObsoleteAttribute>()
.FirstOrDefault();
if (deprecatedAttr is not null)
{
operation.Deprecated = true;
operation.Description = $"DEPRECATED: {deprecatedAttr.Message}";
}
return Task.CompletedTask;
}
}
builder.Services.AddOpenApi(options =>
{
options.AddOperationTransformer<DeprecationTransformer>();
});操作转换器可修改OpenAPI文档中的单个操作(端点)。可用于添加每个操作的元数据、示例或条件逻辑。
csharp
public sealed class DeprecationTransformer : IOpenApiOperationTransformer
{
public Task TransformAsync(
OpenApiOperation operation,
OpenApiOperationTransformerContext context,
CancellationToken cancellationToken)
{
var deprecatedAttr = context.Description.ActionDescriptor
.EndpointMetadata
.OfType<ObsoleteAttribute>()
.FirstOrDefault();
if (deprecatedAttr is not null)
{
operation.Deprecated = true;
operation.Description = $"DEPRECATED: {deprecatedAttr.Message}";
}
return Task.CompletedTask;
}
}
builder.Services.AddOpenApi(options =>
{
options.AddOperationTransformer<DeprecationTransformer>();
});Schema Customization
自定义Schema
Customize how .NET types map to OpenAPI schemas using schema transformers:
csharp
builder.Services.AddOpenApi(options =>
{
options.AddSchemaTransformer((schema, context, ct) =>
{
// Add example values for known types
if (context.JsonTypeInfo.Type == typeof(ProductDto))
{
schema.Example = new OpenApiObject
{
["id"] = new OpenApiInteger(1),
["name"] = new OpenApiString("Widget"),
["price"] = new OpenApiDouble(19.99)
};
}
return Task.CompletedTask;
});
});可使用Schema转换器自定义.NET类型到OpenAPI Schema的映射方式:
csharp
builder.Services.AddOpenApi(options =>
{
options.AddSchemaTransformer((schema, context, ct) =>
{
// 为已知类型添加示例值
if (context.JsonTypeInfo.Type == typeof(ProductDto))
{
schema.Example = new OpenApiObject
{
["id"] = new OpenApiInteger(1),
["name"] = new OpenApiString("Widget"),
["price"] = new OpenApiDouble(19.99)
};
}
return Task.CompletedTask;
});
});Enriching Endpoint Metadata
丰富端点元数据
Use fluent methods on endpoint builders to provide richer OpenAPI metadata:
csharp
products.MapGet("/{id:int}", GetProductById)
.WithName("GetProductById")
.WithSummary("Get a product by its ID")
.WithDescription("Returns the product details for the specified ID, or 404 if not found.")
.WithTags("Products")
.Produces<Product>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status404NotFound);使用端点构建器的链式方法提供更丰富的OpenAPI元数据:
csharp
products.MapGet("/{id:int}", GetProductById)
.WithName("GetProductById")
.WithSummary("Get a product by its ID")
.WithDescription("Returns the product details for the specified ID, or 404 if not found.")
.WithTags("Products")
.Produces<Product>(StatusCodes.Status200OK)
.ProducesProblem(StatusCodes.Status404NotFound);Swashbuckle Migration
Swashbuckle迁移
Swashbuckle () is no longer actively maintained. It does not support OpenAPI 3.1. Existing projects should plan migration to .
Swashbuckle.AspNetCoreMicrosoft.AspNetCore.OpenApiWhen Swashbuckle is still needed: Projects on .NET 8 that cannot upgrade to .NET 9+, or projects that depend on Swashbuckle-specific features (SwaggerUI with deep customization, ISchemaFilter pipelines) may continue using Swashbuckle while planning migration.
Swashbuckle()已不再积极维护,且不支持OpenAPI 3.1。现有项目应规划迁移至。
Swashbuckle.AspNetCoreMicrosoft.AspNetCore.OpenApi仍需使用Swashbuckle的场景: 无法升级到.NET 9+的.NET 8项目,或依赖Swashbuckle特定功能(深度自定义的SwaggerUI、ISchemaFilter管道)的项目,可继续使用Swashbuckle并同时规划迁移。
Migration Steps
迁移步骤
- Remove Swashbuckle packages:
xml
<!-- Remove these -->
<!-- <PackageReference Include="Swashbuckle.AspNetCore" Version="..." /> -->
<!-- <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="..." /> -->- Replace service registration:
csharp
// Before (Swashbuckle)
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
// After (Microsoft.AspNetCore.OpenApi)
builder.Services.AddOpenApi();- Replace middleware:
csharp
// Before (Swashbuckle)
app.UseSwagger();
app.UseSwaggerUI();
// After (built-in)
app.MapOpenApi(); // Serves raw OpenAPI JSON at /openapi/v1.json- For Swagger UI, add a standalone UI package or use Scalar:
csharp
// Option 1: Scalar (modern, built-in support in .NET 10)
// <PackageReference Include="Aspire.Dashboard.Components.Scalar" ... /> or use MapScalarApiReference
app.MapScalarApiReference(); // .NET 10
// Option 2: Swagger UI standalone
// <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="..." />
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/openapi/v1.json", "v1");
});- Migrate Swashbuckle filters to transformers:
| Swashbuckle concept | Built-in replacement |
|---|---|
| |
| |
| Schema transformers via |
| |
| |
- 移除Swashbuckle包:
xml
<!-- 移除以下内容 -->
<!-- <PackageReference Include="Swashbuckle.AspNetCore" Version="..." /> -->
<!-- <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="..." /> -->- 替换服务注册代码:
csharp
// 之前(Swashbuckle)
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
// 之后(Microsoft.AspNetCore.OpenApi)
builder.Services.AddOpenApi();- 替换中间件:
csharp
// 之前(Swashbuckle)
app.UseSwagger();
app.UseSwaggerUI();
// 之后(内置方案)
app.MapOpenApi(); // 在 /openapi/v1.json 提供原始OpenAPI JSON数据- 对于Swagger UI,添加独立UI包或使用Scalar:
csharp
// 选项1:Scalar(现代化方案,.NET 10内置支持)
// <PackageReference Include="Aspire.Dashboard.Components.Scalar" ... /> 或使用 MapScalarApiReference
app.MapScalarApiReference(); // .NET 10
// 选项2:独立Swagger UI
// <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="..." />
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/openapi/v1.json", "v1");
});- 将Swashbuckle过滤器迁移为转换器:
| Swashbuckle概念 | 内置替代方案 |
|---|---|
| |
| |
| 通过 |
| |
| |
NSwag
NSwag
NSwag is an alternative OpenAPI toolchain that includes document generation, client generation (C#, TypeScript), and a UI. It is useful when you need generated API clients or when integrating with non-.NET consumers.
NSwag是一套替代OpenAPI工具链,包含文档生成、客户端生成(C#、TypeScript)和UI界面。当你需要生成API客户端或与非.NET消费者集成时,它会很有用。
Document Generation
文档生成
csharp
// <PackageReference Include="NSwag.AspNetCore" Version="14.*" />
builder.Services.AddOpenApiDocument(options =>
{
options.Title = "Products API";
options.Version = "v1";
options.DocumentName = "v1";
});
var app = builder.Build();
app.UseOpenApi(); // Serves /swagger/v1/swagger.json
app.UseSwaggerUi(); // Serves /swagger UIcsharp
// <PackageReference Include="NSwag.AspNetCore" Version="14.*" />
builder.Services.AddOpenApiDocument(options =>
{
options.Title = "Products API";
options.Version = "v1";
options.DocumentName = "v1";
});
var app = builder.Build();
app.UseOpenApi(); // 在 /swagger/v1/swagger.json 提供文档
app.UseSwaggerUi(); // 在 /swagger 提供UI界面Client Generation
客户端生成
NSwag generates typed C# or TypeScript clients from OpenAPI specs:
bash
undefinedNSwag可从OpenAPI规范生成类型化的C#或TypeScript客户端:
bash
undefinedInstall NSwag CLI
安装NSwag CLI
dotnet tool install --global NSwag.ConsoleCore
dotnet tool install --global NSwag.ConsoleCore
Generate C# client from OpenAPI spec
从OpenAPI规范生成C#客户端
nswag openapi2csclient /input:https://api.example.com/openapi/v1.json
/output:GeneratedClient.cs
/namespace:MyApp.ApiClient
/generateClientInterfaces:true
/output:GeneratedClient.cs
/namespace:MyApp.ApiClient
/generateClientInterfaces:true
**Recommendation:** Use `Microsoft.AspNetCore.OpenApi` for document generation. Use NSwag CLI or Kiota for client generation from the resulting OpenAPI spec. Avoid using NSwag for both generation and serving in new projects.
---nswag openapi2csclient /input:https://api.example.com/openapi/v1.json
/output:GeneratedClient.cs
/namespace:MyApp.ApiClient
/generateClientInterfaces:true
/output:GeneratedClient.cs
/namespace:MyApp.ApiClient
/generateClientInterfaces:true
**建议:** 使用`Microsoft.AspNetCore.OpenApi`进行文档生成。使用NSwag CLI或Kiota从生成的OpenAPI规范生成客户端。新项目中避免同时使用NSwag进行文档生成和服务托管。
---OpenAPI 3.1 (.NET 10)
OpenAPI 3.1(.NET 10)
.NET 10 introduces full OpenAPI 3.1 support with JSON Schema draft 2020-12 compliance. Key improvements over 3.0:
- Nullable types: Uses JSON Schema instead of
type: ["string", "null"]nullable: true - Discriminator improvements: Better oneOf/anyOf support for polymorphic types
- Webhooks: First-class webhook definitions
- JSON Schema alignment: Full compatibility with JSON Schema draft 2020-12 tooling
csharp
// .NET 10: OpenAPI 3.1 is the default
// <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.*" />
builder.Services.AddOpenApi(options =>
{
// Explicitly set version if needed (3.1 is default in .NET 10)
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});Gotcha: Swashbuckle does not support OpenAPI 3.1. Projects requiring 3.1 features must migrate to .
Microsoft.AspNetCore.OpenApi.NET 10引入了对OpenAPI 3.1的完整支持,兼容JSON Schema draft 2020-12规范。相比3.0的主要改进:
- 可空类型: 使用JSON Schema 替代
type: ["string", "null"]nullable: true - 鉴别器优化: 对多态类型的oneOf/anyOf支持更完善
- Webhooks: 原生支持Webhook定义
- JSON Schema对齐: 与JSON Schema draft 2020-12工具完全兼容
csharp
// .NET 10:默认使用OpenAPI 3.1
// <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.*" />
builder.Services.AddOpenApi(options =>
{
// 若需要可显式设置版本(.NET 10中默认是3.1)
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});注意事项: Swashbuckle不支持OpenAPI 3.1。需要使用3.1特性的项目必须迁移至。
Microsoft.AspNetCore.OpenApiAgent Gotchas
常见误区
- Do not pin mismatched major versions of -- the package version must match the project's target framework major version. Do not mix incompatible OpenAPI stacks (e.g., Swashbuckle + built-in) in the same project.
Microsoft.AspNetCore.OpenApi - Do not recommend Swashbuckle for new .NET 9+ projects -- it is no longer actively maintained. Use the built-in instead.
Microsoft.AspNetCore.OpenApi - Do not say Swashbuckle is "deprecated" -- it is not formally deprecated, but it is no longer actively maintained. Say "preferred" or "recommended" when referring to the built-in alternative.
- Do not forget the Swagger UI replacement -- only serves the raw JSON spec. Add Scalar, Swagger UI standalone, or another UI separately.
MapOpenApi() - Do not mix Swashbuckle and built-in OpenAPI in the same project -- they generate conflicting documents. Choose one approach.
- Do not hardcode ASP.NET shared-framework package versions -- packages like must match the project TFM major version.
Microsoft.AspNetCore.OpenApi
- 不要固定不匹配主版本的包版本——包版本必须与项目目标框架的主版本号匹配。不要在同一项目中混用不兼容的OpenAPI栈(如Swashbuckle + 内置方案)。
Microsoft.AspNetCore.OpenApi - 不要为.NET 9+新项目推荐Swashbuckle——它已不再积极维护。应使用内置的。
Microsoft.AspNetCore.OpenApi - 不要说Swashbuckle已“废弃”——它并未被正式废弃,只是不再积极维护。提及官方替代方案时使用“首选”或“推荐”表述。
- 不要忘记替换Swagger UI——仅提供原始JSON规范。需单独添加Scalar、独立Swagger UI或其他UI界面。
MapOpenApi() - 不要在同一项目中混用Swashbuckle和内置OpenAPI方案——它们会生成冲突的文档。请选择其中一种方案。
- 不要硬编码ASP.NET共享框架包版本——像这样的包版本必须与项目TFM主版本匹配。
Microsoft.AspNetCore.OpenApi
Prerequisites
前置要求
- .NET 9.0+ for (included in default project templates)
Microsoft.AspNetCore.OpenApi - .NET 10.0 for OpenAPI 3.1, JSON Schema draft 2020-12, and Scalar integration
- (optional) for NSwag-based generation and UI
NSwag.AspNetCore - (legacy) for existing projects not yet migrated
Swashbuckle.AspNetCore
- 使用需要.NET 9.0+(默认包含在项目模板中)
Microsoft.AspNetCore.OpenApi - 使用OpenAPI 3.1、JSON Schema draft 2020-12和Scalar集成需要.NET 10.0
- (可选)使用NSwag需要
NSwag.AspNetCore - (遗留)现有项目使用Swashbuckle需要
Swashbuckle.AspNetCore