mcpField
D
dotnet-openapi

dotnet-openapi

github.com/wshaddix开发8675 次安装35 周前更新
代码仓库

关于 dotnet-openapi

面向 ASP.NET Core 开发者的 OpenAPI 集成指南,介绍文档生成、转换和架构定制,并说明 Microsoft.AspNetCore.OpenApi、Swashbuckle 与 NSwag 的用法。还涵盖迁移以及 .NET 10 中的 OpenAPI 3.1。

主要功能

  1. 01生成和配置 OpenAPI 文档
  2. 02使用文档、操作及架构转换器
  3. 03丰富端点的 OpenAPI 元数据
  4. 04从 Swashbuckle 迁移
  5. 05通过 NSwag 生成 C# 或 TypeScript 客户端

适用场景

  1. 01为 ASP.NET Core API 生成规范文档
  2. 02按 API 版本或功能组拆分文档
  3. 03为端点添加说明和响应元数据
  4. 04从 OpenAPI 规范生成类型化客户端

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-openapi

安装后在 Claude Code 中输入/dotnet-openapi确认已加载。

详细介绍

dotnet-openapi

ASP.NET Core 的 OpenAPI/Swagger 集成。Microsoft.AspNetCore.OpenApi 是 .NET 9+ 推荐的第一方方案,也是新项目模板中的默认方案。Swashbuckle 已不再积极维护;使用 Swashbuckle 的现有项目应规划迁移。NSwag 仍是客户端生成和高级场景的替代方案。

不在此范围内: Minimal 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(推荐)

Microsoft.AspNetCore.OpenApi 是适用于 ASP.NET Core 9+ 的第一方 OpenAPI 包,并默认包含在新项目模板中。.NET 10 新增了对 OpenAPI 3.1 的支持,并符合 JSON Schema draft 2020-12 规范。

基本设置
// 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
}
多个文档

为每个 API 版本或功能组生成单独的 OpenAPI 文档:

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

文档转换器

文档转换器会在生成 OpenAPI 文档后对其进行修改。可使用它们添加服务器信息、安全方案或自定义元数据。

IOpenApiDocumentTransformer
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>();
});
Lambda 文档转换器

对于简单的转换,可以使用 lambda 重载:

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 = "[email protected]"
            }
        };
        return Task.CompletedTask;
    });
});

操作转换器

操作转换器会修改 OpenAPI 文档中的单个操作(端点)。可使用它们添加每个操作的元数据、示例或条件逻辑。

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>();
});

架构自定义

使用架构转换器自定义 .NET 类型到 OpenAPI 架构的映射:

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;
    });
});
丰富端点元数据

使用端点构建器上的 fluent 方法提供更丰富的 OpenAPI 元数据:

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 迁移

Swashbuckle(Swashbuckle.AspNetCore)已不再积极维护。它不支持 OpenAPI 3.1。现有项目应规划迁移到 Microsoft.AspNetCore.OpenApi。

仍需使用 Swashbuckle 的情况: 无法升级到 .NET 9+ 的 .NET 8 项目,或依赖 Swashbuckle 特有功能(可深度自定义的 SwaggerUI、ISchemaFilter 管道)的项目,可以在规划迁移期间继续使用 Swashbuckle。

迁移步骤
  1. 移除 Swashbuckle 包:



  1. 替换服务注册:
// Before (Swashbuckle)
builder.Services.AddSwaggerGen(options =>
{
    options.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});

// After (Microsoft.AspNetCore.OpenApi)
builder.Services.AddOpenApi();
  1. 替换中间件:
// Before (Swashbuckle)
app.UseSwagger();
app.UseSwaggerUI();

// After (built-in)
app.MapOpenApi(); // Serves raw OpenAPI JSON at /openapi/v1.json
  1. 对于 Swagger UI,添加独立的 UI 包或使用 Scalar:
// 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");
});
  1. 将 Swashbuckle 筛选器迁移为转换器:
Swashbuckle 概念内置替代方案
IDocumentFilterIOpenApiDocumentTransformer
IOperationFilterIOpenApiOperationTransformer
ISchemaFilter通过 AddSchemaTransformer 使用架构转换器
[SwaggerOperation].WithSummary()、.WithDescription()
[SwaggerResponse].Produces<T>()、TypedResults

NSwag

NSwag 是一套替代的 OpenAPI 工具链,包含文档生成、客户端生成(C#、TypeScript)和 UI。如果需要生成 API 客户端,或需要与非 .NET 使用方集成,它会很有用。

文档生成
// <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 UI
客户端生成

NSwag 可根据 OpenAPI 规范生成类型化的 C# 或 TypeScript 客户端:

# Install NSwag CLI
dotnet tool install --global NSwag.ConsoleCore

# Generate C# client from OpenAPI spec
nswag openapi2csclient /input:https://api.example.com/openapi/v1.json \
    /output:GeneratedClient.cs \
    /namespace:MyApp.ApiClient \
    /generateClientInterfaces:true

建议: 使用 Microsoft.AspNetCore.OpenApi 生成文档。使用 NSwag CLI 或 Kiota 根据生成的 OpenAPI 规范生成客户端。新项目应避免同时使用 NSwag 进行生成和服务。


OpenAPI 3.1(.NET 10)

.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 工具完全兼容
// .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;
});

注意事项: Swashbuckle 不支持 OpenAPI 3.1。需要使用 3.1 功能的项目必须迁移到 Microsoft.AspNetCore.OpenApi。


Agent 注意事项

  1. 不要固定使用与 Microsoft.AspNetCore.OpenApi 主版本不匹配的版本 —— 包版本必须与项目的目标框架主版本一致。不要在同一项目中混用不兼容的 OpenAPI 技术栈(例如 Swashbuckle 与内置方案)。
  2. 不要为新的 .NET 9+ 项目推荐 Swashbuckle —— 它已不再积极维护。请改用内置的 Microsoft.AspNetCore.OpenApi。
  3. 不要称 Swashbuckle 为“已弃用” —— 它并未正式弃用,但已不再积极维护。提及内置替代方案时,请使用“首选”或“推荐”。
  4. 不要忘记替换 Swagger UI —— MapOpenApi() 只提供原始 JSON 规范。请另外添加 Scalar、独立版 Swagger UI 或其他 UI。
  5. 不要在同一项目中混用 Swashbuckle 和内置 OpenAPI —— 它们会生成相互冲突的文档。请选择一种方案。
  6. 不要对 ASP.NET 共享框架包的版本进行硬编码 —— Microsoft.AspNetCore.OpenApi 等包必须与项目 TFM 主版本一致。

前置条件

  • 使用 Microsoft.AspNetCore.OpenApi 需要 .NET 9.0+(包含在默认项目模板中)
  • 使用 OpenAPI 3.1、JSON Schema draft 2020-12 和 Scalar 集成需要 .NET 10.0
  • NSwag.AspNetCore(可选),用于基于 NSwag 的生成和 UI
  • Swashbuckle.AspNetCore(旧版),适用于尚未迁移的现有项目

参考资料

评论

支持 Markdown