基本 API 應用程式中的 OpenAPI 支援

OpenAPI 規格是記錄 HTTP API 的程式設計語言無關標準。 透過內建 API 和開放原始碼程式庫的組合,在基本 API 中支援此標準。 應用程式中的 OpenAPI 整合有三個重要層面:

  • 產生應用程式中端點的相關資訊。
  • 將資訊收集成符合 OpenAPI 結構描述的格式。
  • 透過視覺化 UI 或序列化檔案公開產生的 OpenAPI 結構描述。

基本 API 針對透過 Microsoft.AspNetCore.OpenApi 封裝產生應用程式中端點的相關資訊提供內建支援。 透過視覺 UI 公開產生的 OpenAPI 定義需要第三方封裝。

下列程式碼是由 ASP.NET Core 基本 Web API 範本所產生,並使用 OpenAPI:

using Microsoft.AspNetCore.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateTime.Now.AddDays(index),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();

app.Run();

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

在上述醒目提示的程式碼中:

  • 下一節會說明 Microsoft.AspNetCore.OpenApi
  • AddEndpointsApiExplorer:將應用程式設定為使用 API 總管來探索及描述具有預設註釋的端點。 WithOpenApi 會以從 Microsoft.AspNetCore.OpenApi 封裝產生的註釋來覆寫 API 總管所產生的相符預設註釋。
  • UseSwagger 會新增 Swagger 中介軟體
  • UseSwaggerUI 會在開發模式中啟用 Swagger UI 工具的內嵌版本。
  • WithName:端點上的 IEndpointNameMetadata 會用於產生連結,並視為指定端點 OpenAPI 規格中的作業識別碼。
  • 本文稍後將說明 WithOpenApi

Microsoft.AspNetCore.OpenApi NuGet 封裝

ASP.NET Core 提供 Microsoft.AspNetCore.OpenApi 封裝來與端點的 OpenAPI 規格互動。 封裝會作為在 Microsoft.AspNetCore.OpenApi 封裝中定義的 OpenAPI 模型與在基本 API 中定義的端點之間的連結。 封裝提供 API,其會檢查端點的參數、回應和中繼資料,以建構用來描述端點的 OpenAPI 註釋型別。

Microsoft.AspNetCore.OpenApi 會新增為專案檔的 PackageReference:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>    
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.*-*" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
  </ItemGroup>

</Project>

使用 Swashbuckle.AspNetCore 搭配 Microsoft.AspNetCore.OpenApi 時,必須使用 Swashbuckle.AspNetCore 6.4.0 或更新版本。 Microsoft.OpenApi 1.4.3 或更新版本必須用來利用 WithOpenApi 叫用中的複製建構函式。

透過 WithOpenApi 將 OpenAPI 註釋新增至端點

在端點上呼叫 WithOpenApi 會新增至端點的中繼資料。 此中繼資料可以:

  • Swashbuckle.AspNetCore 等第三方封裝中取用。
  • 顯示在 Swagger 使用者介面中或產生 YAML 或 JSON,用來定義 API。
app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();

WithOpenApi 中修改 OpenAPI 註釋

WithOpenApi 方法會接受可用來修改 OpenAPI 註釋的函式。 例如,在下列程式碼中,描述會新增至端點的第一個參數:

app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
    var parameter = generatedOperation.Parameters[0];
    parameter.Description = "The ID associated with the created Todo";
    return generatedOperation;
});

將作業識別碼新增至 OpenAPI

作業識別碼可用來唯一識別 OpenAPI 中的指定端點。 WithName 擴充方法可用來設定方法所使用的作業識別碼。

app.MapGet("/todoitems2", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithName("GetToDoItems");

或者,可以直接在 OpenAPI 註釋上設定 OperationId 屬性。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        OperationId = "GetTodos"
    });

將標記新增至 OpenAPI 描述

OpenAPI 支援使用標記物件來分類作業。 這些標記通常用於群組 Swagger UI 中的作業。 藉由叫用具有所需標記的端點上的 WithTags 擴充方法,即可將這些標記新增至作業。

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithTags("TodoGroup");

或者,可以透過 OpenApiTags 擴充方法,在 OpenAPI 註釋上設定 WithOpenApi 的清單。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Tags = new List<OpenApiTag> { new() { Name = "Todos" } }
    });

新增端點摘要或描述

透過叫用 WithOpenApi 擴充方法來新增端點摘要和描述。 在下列程式碼中,摘要會直接在 OpenAPI 註釋上設定。

app.MapGet("/todoitems2", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Summary = "This is a summary",
        Description = "This is a description"
    });

排除 OpenAPI 描述

在下列範例中,/skipme 端點會從產生 OpenAPI 描述排除:

using Microsoft.AspNetCore.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.MapGet("/swag", () => "Hello Swagger!")
    .WithOpenApi();
app.MapGet("/skipme", () => "Skipping Swagger.")
                    .ExcludeFromDescription();

app.Run();

將 API 標示為過時

若要將端點標示為過時,請在 OpenAPI 註釋上設定 Deprecated 屬性。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Deprecated = true
    });

描述回應類型

OpenAPI 支援提供從 API 傳回的回應描述。 基本 API 針對設定端點的回應型別支援三個策略:

Produces 擴充方法可用來將 Produces 中繼資料新增至端點。 如果未提供任何參數,擴充方法會在 200 狀態碼和 application/json 內容型別下填入目標型別的中繼資料。

app
    .MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .Produces<IList<Todo>>();

在端點路由處理常式的實作中使用 TypedResults,會自動包含端點的回應型別中繼資料。 例如,下列程式碼會自動以具有 application/json 內容型別的 200 狀態碼的回應來註釋端點。

app.MapGet("/todos", async (TodoDb db) =>
{
    var todos = await db.Todos.ToListAsync());
    return TypedResults.Ok(todos);
});

設定 ProblemDetails 的回應

設定可能傳回 ProblemDetails 回應的端點的回應型別時,ProducesProblem 擴充方法或 TypedResults.Problem 可用來將適當的註釋新增至端點的中繼資料。

當上述其中一個策略未提供明確註釋時,架構會藉由檢查回應的簽章來嘗試判斷預設回應型別。 此預設回應會填入在 OpenAPI 定義中的 200 狀態碼底下。

多個回應型別

如果端點可以在不同案例中傳回不同的回應型別,您可以透過下列方式提供中繼資料:

  • 呼叫 Produces 擴充方法多次,如下列範例所示:

    app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
             await db.Todos.FindAsync(id) 
             is Todo todo
             ? Results.Ok(todo) 
             : Results.NotFound())
       .Produces<Todo>(StatusCodes.Status200OK)
       .Produces(StatusCodes.Status404NotFound);
    
  • 在簽章和 TypedResults 處理常式主體中使用 Results<TResult1,TResult2,TResultN>,如下列範例所示:

    app.MapGet("/book{id}", Results<Ok<Book>, NotFound> (int id, List<Book> bookList) =>
    {
        return bookList.FirstOrDefault((i) => i.Id == id) is Book book
         ? TypedResults.Ok(book)
         : TypedResults.NotFound();
    });
    

    Results<TResult1,TResult2,TResultN>等位型別會宣告路由處理常式傳回多個 IResult 實作的具體型別,而實作 IEndpointMetadataProvider 的任何型別都會對端點的中繼資料造成貢獻。

    等位型別會實作隱含轉換運算子。 這些運算子可讓編譯器自動將泛型引數中指定的型別轉換成等位型別的執行個體。 此功能會有的附加優點為提供編譯時間檢查,以確定路由處理常式只會傳回其宣告會執行的結果。 嘗試傳回未宣告為其中一個泛型引數的型別至 Results<TResult1,TResult2,TResultN> 會產生編譯錯誤。

描述要求本文和參數

除了描述端點所傳回的型別之外,OpenAPI 也支援註釋 API 所取用的輸入。 這些輸入可分為兩個類別:

  • 出現在路徑、查詢字串、標頭或 cookie 中的參數
  • 隨著要求本文傳輸的資料

架構會根據路由處理常式的簽章,自動推斷路徑、查詢和標頭字串中要求參數的型別。

若要定義傳送為要求本文的輸入型別,請使用 Accepts 擴充方法來定義要求處理常式所預期的物件型別和內容型別,以設定屬性。 在下列範例中,端點會接受要求本文中具有預期 application/xml 內容型別的 Todo 物件。

app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
  .Accepts<Todo>("application/xml");

除了 Accepts 擴充方法之外,參數型別也可以藉由實作 IEndpointParameterMetadataProvider 介面來描述自己的註釋。 例如,下列 Todo 型別會新增需要具有 application/xml 內容型別要求本文的註釋。

public class Todo : IEndpointParameterMetadataProvider
{
    public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
    {
        builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
    }
}

如果未提供明確的註釋,如果端點處理常式中有要求主體參數,架構會嘗試判斷預設要求型別。 推斷會使用下列啟發學習法來產生註釋:

  • 透過 [FromForm] 屬性從表單讀取的要求本文參數會使用 multipart/form-data 內容型別描述。
  • 所有其他要求主體參數都會使用 application/json 內容型別來描述。
  • 如果要求主體可為 Null,或 FromBody 屬性上設定 AllowEmpty 屬性,則會將其視為選用。

支援 API 版本設定

基本 API 支援透過 Asp.Versioning.Http 封裝的 API 版本設定。 您可以在 API 版本設定存放庫中找到使用基本 API 設定版本設定的範例。

GitHub 上的 ASP.NET Core OpenAPI 原始程式碼

其他資源

OpenAPI 規格是記錄 HTTP API 的程式設計語言無關標準。 透過內建 API 和開放原始碼程式庫的組合,在基本 API 中支援此標準。 應用程式中的 OpenAPI 整合有三個重要層面:

  • 產生應用程式中端點的相關資訊。
  • 將資訊收集成符合 OpenAPI 結構描述的格式。
  • 透過視覺化 UI 或序列化檔案公開產生的 OpenAPI 結構描述。

基本 API 針對透過 Microsoft.AspNetCore.OpenApi 封裝產生應用程式中端點的相關資訊提供內建支援。 透過視覺 UI 公開產生的 OpenAPI 定義需要第三方封裝。

下列程式碼是由 ASP.NET Core 基本 Web API 範本所產生,並使用 OpenAPI:

using Microsoft.AspNetCore.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

app.MapGet("/weatherforecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateTime.Now.AddDays(index),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();

app.Run();

internal record WeatherForecast(DateTime Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

在上述醒目提示的程式碼中:

  • 下一節會說明 Microsoft.AspNetCore.OpenApi
  • AddEndpointsApiExplorer:將應用程式設定為使用 API 總管來探索及描述具有預設註釋的端點。 WithOpenApi 會以從 Microsoft.AspNetCore.OpenApi 封裝產生的註釋來覆寫 API 總管所產生的相符預設註釋。
  • UseSwagger 會新增 Swagger 中介軟體
  • `UseSwaggerUI` 會啟用 Swagger UI 工具的內嵌版本。
  • WithName:端點上的 IEndpointNameMetadata 會用於產生連結,並視為指定端點 OpenAPI 規格中的作業識別碼。
  • 本文稍後將說明 WithOpenApi

Microsoft.AspNetCore.OpenApi NuGet 封裝

ASP.NET Core 提供 Microsoft.AspNetCore.OpenApi 封裝來與端點的 OpenAPI 規格互動。 封裝會作為在 Microsoft.AspNetCore.OpenApi 封裝中定義的 OpenAPI 模型與在基本 API 中定義的端點之間的連結。 封裝提供 API,其會檢查端點的參數、回應和中繼資料,以建構用來描述端點的 OpenAPI 註釋型別。

Microsoft.AspNetCore.OpenApi 會新增為專案檔的 PackageReference:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>    
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.*-*" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
  </ItemGroup>

</Project>

使用 Swashbuckle.AspNetCore 搭配 Microsoft.AspNetCore.OpenApi 時,必須使用 Swashbuckle.AspNetCore 6.4.0 或更新版本。 Microsoft.OpenApi 1.4.3 或更新版本必須用來利用 WithOpenApi 叫用中的複製建構函式。

透過 WithOpenApi 將 OpenAPI 註釋新增至端點

在端點上呼叫 WithOpenApi 會新增至端點的中繼資料。 此中繼資料可以:

  • Swashbuckle.AspNetCore 等第三方封裝中取用。
  • 顯示在 Swagger 使用者介面中或產生 YAML 或 JSON,用來定義 API。
app.MapPost("/todoitems/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi();

WithOpenApi 中修改 OpenAPI 註釋

WithOpenApi 方法會接受可用來修改 OpenAPI 註釋的函式。 例如,在下列程式碼中,描述會新增至端點的第一個參數:

app.MapPost("/todo2/{id}", async (int id, Todo todo, TodoDb db) =>
{
    todo.Id = id;
    db.Todos.Add(todo);
    await db.SaveChangesAsync();

    return Results.Created($"/todoitems/{todo.Id}", todo);
})
.WithOpenApi(generatedOperation =>
{
    var parameter = generatedOperation.Parameters[0];
    parameter.Description = "The ID associated with the created Todo";
    return generatedOperation;
});

將作業識別碼新增至 OpenAPI

作業識別碼可用來唯一識別 OpenAPI 中的指定端點。 WithName 擴充方法可用來設定方法所使用的作業識別碼。

app.MapGet("/todoitems2", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithName("GetToDoItems");

或者,可以直接在 OpenAPI 註釋上設定 OperationId 屬性。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        OperationId = "GetTodos"
    });

將標記新增至 OpenAPI 描述

OpenAPI 支援使用標記物件來分類作業。 這些標記通常用於群組 Swagger UI 中的作業。 藉由叫用具有所需標記的端點上的 WithTags 擴充方法,即可將這些標記新增至作業。

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithTags("TodoGroup");

或者,可以透過 OpenApiTags 擴充方法,在 OpenAPI 註釋上設定 WithOpenApi 的清單。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Tags = new List<OpenApiTag> { new() { Name = "Todos" } }
    });

新增端點摘要或描述

透過叫用 WithOpenApi 擴充方法來新增端點摘要和描述。 在下列程式碼中,摘要會直接在 OpenAPI 註釋上設定。

app.MapGet("/todoitems2", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Summary = "This is a summary",
        Description = "This is a description"
    });

排除 OpenAPI 描述

在下列範例中,/skipme 端點會從產生 OpenAPI 描述排除:

using Microsoft.AspNetCore.OpenApi;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.MapGet("/swag", () => "Hello Swagger!")
    .WithOpenApi();
app.MapGet("/skipme", () => "Skipping Swagger.")
                    .ExcludeFromDescription();

app.Run();

將 API 標示為過時

若要將端點標示為過時,請在 OpenAPI 註釋上設定 Deprecated 屬性。

app.MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .WithOpenApi(operation => new(operation)
    {
        Deprecated = true
    });

描述回應類型

OpenAPI 支援提供從 API 傳回的回應描述。 基本 API 針對設定端點的回應型別支援三個策略:

Produces 擴充方法可用來將 Produces 中繼資料新增至端點。 如果未提供任何參數,擴充方法會在 200 狀態碼和 application/json 內容型別下填入目標型別的中繼資料。

app
    .MapGet("/todos", async (TodoDb db) => await db.Todos.ToListAsync())
    .Produces<IList<Todo>>();

在端點路由處理常式的實作中使用 TypedResults,會自動包含端點的回應型別中繼資料。 例如,下列程式碼會自動以具有 application/json 內容型別的 200 狀態碼的回應來註釋端點。

app.MapGet("/todos", async (TodoDb db) =>
{
    var todos = await db.Todos.ToListAsync());
    return TypedResults.Ok(todos);
});

設定 ProblemDetails 的回應

設定可能傳回 ProblemDetails 回應的端點的回應型別時,ProducesProblem 擴充方法或 TypedResults.Problem 可用來將適當的註釋新增至端點的中繼資料。

當上述其中一個策略未提供明確註釋時,架構會藉由檢查回應的簽章來嘗試判斷預設回應型別。 此預設回應會填入在 OpenAPI 定義中的 200 狀態碼底下。

多個回應型別

如果端點可以在不同案例中傳回不同的回應型別,您可以透過下列方式提供中繼資料:

  • 呼叫 Produces 擴充方法多次,如下列範例所示:

    app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
             await db.Todos.FindAsync(id) 
             is Todo todo
             ? Results.Ok(todo) 
             : Results.NotFound())
       .Produces<Todo>(StatusCodes.Status200OK)
       .Produces(StatusCodes.Status404NotFound);
    
  • 在簽章和 TypedResults 處理常式主體中使用 Results<TResult1,TResult2,TResultN>,如下列範例所示:

    app.MapGet("/book{id}", Results<Ok<Book>, NotFound> (int id, List<Book> bookList) =>
    {
        return bookList.FirstOrDefault((i) => i.Id == id) is Book book
         ? TypedResults.Ok(book)
         : TypedResults.NotFound();
    });
    

    Results<TResult1,TResult2,TResultN>等位型別會宣告路由處理常式傳回多個 IResult 實作的具體型別,而實作 IEndpointMetadataProvider 的任何型別都會對端點的中繼資料造成貢獻。

    等位型別會實作隱含轉換運算子。 這些運算子可讓編譯器自動將泛型引數中指定的型別轉換成等位型別的執行個體。 此功能會有的附加優點為提供編譯時間檢查,以確定路由處理常式只會傳回其宣告會執行的結果。 嘗試傳回未宣告為其中一個泛型引數的型別至 Results<TResult1,TResult2,TResultN> 會產生編譯錯誤。

描述要求本文和參數

除了描述端點所傳回的型別之外,OpenAPI 也支援註釋 API 所取用的輸入。 這些輸入可分為兩個類別:

  • 出現在路徑、查詢字串、標頭或 cookie 中的參數
  • 隨著要求本文傳輸的資料

架構會根據路由處理常式的簽章,自動推斷路徑、查詢和標頭字串中要求參數的型別。

若要定義傳送為要求本文的輸入型別,請使用 Accepts 擴充方法來定義要求處理常式所預期的物件型別和內容型別,以設定屬性。 在下列範例中,端點會接受要求本文中具有預期 application/xml 內容型別的 Todo 物件。

app.MapPost("/todos/{id}", (int id, Todo todo) => ...)
  .Accepts<Todo>("application/xml");

除了 Accepts 擴充方法之外,參數型別也可以藉由實作 IEndpointParameterMetadataProvider 介面來描述自己的註釋。 例如,下列 Todo 型別會新增需要具有 application/xml 內容型別要求本文的註釋。

public class Todo : IEndpointParameterMetadataProvider
{
    public static void PopulateMetadata(ParameterInfo parameter, EndpointBuilder builder)
    {
        builder.Metadata.Add(new ConsumesAttribute(typeof(Todo), isOptional: false, "application/xml"));
    }
}

如果未提供明確的註釋,如果端點處理常式中有要求主體參數,架構會嘗試判斷預設要求型別。 推斷會使用下列啟發學習法來產生註釋:

  • 透過 [FromForm] 屬性從表單讀取的要求本文參數會使用 multipart/form-data 內容型別描述。
  • 所有其他要求主體參數都會使用 application/json 內容型別來描述。
  • 如果要求主體可為 Null,或 FromBody 屬性上設定 AllowEmpty 屬性,則會將其視為選用。

支援 API 版本設定

基本 API 支援透過 Asp.Versioning.Http 封裝的 API 版本設定。 您可以在 API 版本設定存放庫中找到使用基本 API 設定版本設定的範例。

GitHub 上的 ASP.NET Core OpenAPI 原始程式碼

其他資源

應用程式可以使用 Swashbuckle 來描述路由處理常式的 OpenAPI 規格

下列程式碼是具有 OpenAPI 支援的一般 ASP.NET Core 應用程式:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new() { Title = builder.Environment.ApplicationName,
                               Version = "v1" });
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger(); // UseSwaggerUI Protected by if (env.IsDevelopment())
    app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json",
                                    $"{builder.Environment.ApplicationName} v1"));
}

app.MapGet("/swag", () => "Hello Swagger!");

app.Run();

排除 OpenAPI 描述

在下列範例中,/skipme 端點會從產生 OpenAPI 描述排除:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(); // UseSwaggerUI Protected by if (env.IsDevelopment())
}

app.MapGet("/swag", () => "Hello Swagger!");
app.MapGet("/skipme", () => "Skipping Swagger.")
                    .ExcludeFromDescription();

app.Run();

描述回應類型

下列範例會使用內建的結果型別來自訂回應:

app.MapGet("/api/todoitems/{id}", async (int id, TodoDb db) =>
         await db.Todos.FindAsync(id) 
         is Todo todo
         ? Results.Ok(todo) 
         : Results.NotFound())
   .Produces<Todo>(StatusCodes.Status200OK)
   .Produces(StatusCodes.Status404NotFound);

將作業識別碼新增至 OpenAPI

app.MapGet("/todoitems2", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithName("GetToDoItems");

將標記新增至 OpenAPI 描述

下列程式碼使用 OpenAPI 群組標記

app.MapGet("/todoitems", async (TodoDb db) =>
    await db.Todos.ToListAsync())
    .WithTags("TodoGroup");