開始使用 NSwag 及 ASP.NET Core

作者:Christoph NienaberRico SuterDave Brock

檢視或下載範例程式碼 \(英文\) (如何下載)

NSwag 提供下列功能:

  • 能夠運用 Swagger UI 和 Swagger 產生器。
  • 彈性的程式碼產生功能。

使用 NSwag 時,您不需要現有的 API;您可以使用包含 Swagger 的協力廠商 API,然後產生用戶端實作。 NSwag 可讓您加速開發週期,並輕鬆地因應 API 變更進行調整。

套件安裝

將 NSwag 安裝到:

  • 為實作的 Web API 產生 Swagger 規格。
  • 提供 Swagger UI 以瀏覽並測試 Web API。
  • 提供 Redoc 以新增 Web API 的 API 文件。

若要使用 NSwag ASP.NET Core 中介軟體,請安裝 NSwag.AspNetCore NuGet 套件。 此套件包含用以產生並提供 Swagger 規格、Swagger UI (v2 和 v3) 及 ReDoc UI 的中介軟體。

請使用下列其中一種方法來安裝 NSwag NuGet 套件:

  • 從 [套件管理員主控台] 視窗中:

    • 移至 [檢視]>[其他視窗]>[套件管理員主控台]

    • 瀏覽至 NSwagSample.csproj 檔案所在的目錄

    • 執行以下 命令:

      Install-Package NSwag.AspNetCore
      
  • 從 [管理 NuGet 套件] 對話方塊中:

    • 在 [方案總管]>[管理 NuGet 套件] 中,以滑鼠右鍵按一下專案
    • 將 [套件來源] 設定為 "nuget.org"
    • 在搜尋方塊中輸入 "NSwag.AspNetCore"
    • 從 [瀏覽] 索引標籤中選取 "NSwag.AspNetCore" 套件,並按一下 [安裝]

新增和設定 Swagger 中介軟體

請執行下列步驟,以在您的 ASP.NET Core 應用程式中新增及設定 Swagger:

  • 將 OpenApi 產生器新增至 Program.cs 中的服務集合:
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddOpenApiDocument();
  • 也在 Program.cs 中啟用中介軟體,來提供產生的 OpenApi 規格、Swagger UI 和 Redoc UI:
if (app.Environment.IsDevelopment())
{
    // Add OpenAPI 3.0 document serving middleware
    // Available at: http://localhost:<port>/swagger/v1/swagger.json
    app.UseOpenApi();

    // Add web UIs to interact with the document
    // Available at: http://localhost:<port>/swagger
    app.UseSwaggerUi();
}
  • 啟動應用程式。 瀏覽至:
    • http://localhost:<port>/swagger 以檢視 Swagger UI。
    • http://localhost:<port>/swagger/v1/swagger.json 以檢視 Swagger 規格。

程式碼產生

您可以選擇下列其中一個選項來利用 NSwag 的程式碼產生功能:

使用 NSwagStudio 來產生程式碼

  • 依照 NSwagStudio GitHub 存放庫 \(英文\) 的指示來安裝 NSwagStudio。 在 NSwag 發行頁面上,您可以下載 xcopy 版本,而不需要安裝及管理員權限即可將其啟動。
  • 啟動 NSwagStudio,然後在 [Swagger 規格 URL] 文字方塊中輸入 swagger.json 檔案 URL。 例如: http://localhost:5232/swagger/v1/swagger.json
  • 按一下 [建立本機複本] 按鈕,以產生 Swagger 規格的 JSON 表示法。

NSwag Studio imports the specification and exports a CSharp Client.

  • 在 [輸出] 區域中,按一下 [CSharp 用戶端] 核取方塊。 視您的專案而定,您也可以選擇 [TypeScript Client] \(TypeScript 用戶端\)或 [CSharp Web API Controller] \(CSharp Web API 控制器\)。 如果您選取 [CSharp Web API Controller] \(CSharp Web API 控制器\),服務規格會重建服務,作為反向產生。
  • 按一下 [Generate Outputs] \(產生輸出\),以產生 TodoApi.NSwag 專案 的完整 C# 用戶端實作。 若要查看所產生的用戶端程式碼,請按一下 [CSharp Client] \(CSharp 用戶端\) 索引標籤:
namespace MyNamespace
{
    using System = global::System;

    [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.1.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")]
    public partial class TodoClient
    {
    #pragma warning disable 8618 // Set by constructor via BaseUrl property
        private string _baseUrl;
    #pragma warning restore 8618 // Set by constructor via BaseUrl property
        private System.Net.Http.HttpClient _httpClient;
        private static System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings, true);

        public TodoClient(System.Net.Http.HttpClient httpClient)
        {
            BaseUrl = "http://localhost:5232";
            _httpClient = httpClient;
        }

        private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
        {
            var settings = new Newtonsoft.Json.JsonSerializerSettings();
            UpdateJsonSerializerSettings(settings);
            return settings;
        }

        public string BaseUrl
        {
            get { return _baseUrl; }
            set
            {
                _baseUrl = value;
                if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/"))
                    _baseUrl += '/';
            }
        }
        // code omitted for brevity

提示

C# 用戶端程式碼會根據 [Settings] \(設定\) 索引標籤中的選取項目來產生。修改設定以執行工作,例如重新命名預設的命名空間和產生同步方法。

  • 將產生的 C# 程式碼複製到將取用 API 的用戶端專案中檔案。
  • 開始取用 Web API:
var todoClient = new TodoClient(new HttpClient());

// Gets all to-dos from the API
var allTodos = await todoClient.GetAsync();

// Create a new TodoItem, and save it via the API.
await todoClient.CreateAsync(new TodoItem());

// Get a single to-do by ID
var foundTodo = await todoClient.GetByIdAsync(1);

自訂 API 文件

OpenApi 提供選項來記錄物件模型,以簡化 Web API 的取用作業。

API 資訊與描述

Program.cs 中,更新 AddOpenApiDocument 以設定 Web API 的文件資訊,並納入詳細資訊 (例如作者、授權和描述)。 先匯入 NSwag 命名空間以使用 OpenApi 類別。

using NSwag;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApiDocument(options => {
     options.PostProcess = document =>
     {
         document.Info = new OpenApiInfo
         {
             Version = "v1",
             Title = "ToDo API",
             Description = "An ASP.NET Core Web API for managing ToDo items",
             TermsOfService = "https://example.com/terms",
             Contact = new OpenApiContact
             {
                 Name = "Example Contact",
                 Url = "https://example.com/contact"
             },
             License = new OpenApiLicense
             {
                 Name = "Example License",
                 Url = "https://example.com/license"
             }
         };
     };
});

Swagger UI 會顯示版本資訊:

Swagger UI with version information.

XML 註解

若要啟用 XML 註解,請執行下列步驟:

  • 在 [方案總管] 中以滑鼠右鍵按一下專案,然後選取 Edit <project_name>.csproj
  • 將醒目提示的程式碼行手動新增至 .csproj 檔案:
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

啟用 XML 註解,可提供未記載之公用類型與成員的偵錯資訊。 未記載的類型和成員會以警告訊息表示。 例如,下列訊息指出警告碼 1591 的違規:

warning CS1591: Missing XML comment for publicly visible type or member 'TodoContext'

在專案檔中定義要忽略的警告碼清單 (以分號分隔),即可隱藏警告。 將警告碼附加至 $(NoWarn); 也會套用 C# 預設值

<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

若只要針對特定成員隱藏,請將程式碼放在 #pragma 警告前置處理器指示詞中。 針對不應該透過 API 文件公開的程式碼,此方法非常有用。在下列範例中,會針對整個 TodoContext 類別忽略警告碼 CS1591。 會在類別定義結尾處還原強制執行的警告碼。 以逗號分隔清單指定多個警告碼。

namespace NSwagSample.Models;

#pragma warning disable CS1591
public class TodoContext : DbContext
{
    public TodoContext(DbContextOptions<TodoContext> options) : base(options) { }

    public DbSet<TodoItem> TodoItems => Set<TodoItem>();
}
#pragma warning restore CS1591

資料註解

使用 System.ComponentModel.DataAnnotations 命名空間中找到的屬性來標記模型,以協助驅動 Swagger UI 元件。

[Required] 屬性 (attribute) 新增至 TodoItem 類別的 Name 屬性 (property):

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace NSwagSample.Models;

public class TodoItem
{
    public long Id { get; set; }

    [Required]
    public string Name { get; set; } = null!;

    [DefaultValue(false)]
    public bool IsComplete { get; set; }
}

這個屬性的存在會變更 UI 行為,並改變基礎的 JSON 結構描述:

"TodoItem": {
  "type": "object",
  "additionalProperties": false,
  "required": [
    "name"
  ],
  "properties": {
    "id": {
      "type": "integer",
      "format": "int64"
    },
    "name": {
      "type": "string",
      "minLength": 1
    },
    "isComplete": {
      "type": "boolean",
      "default": false
    }
  }
}

當 Web API 中的資料註釋使用量增加時,UI 和 API 說明頁面會變得更清楚且更有用。

描述回應類型

取用 Web API 的開發人員最關心的是傳回的內容:特別是回應類型和錯誤碼 (如果不是標準的話)。 回應類型和錯誤碼會在 XML 註解及資料註解中表示。

Create 動作在成功時會傳回 HTTP 201 狀態碼。 張貼的要求主體為 null 時,會傳回 HTTP 400 狀態碼。 如果 Swagger UI 中沒有適當的文件,取用者便會缺乏對這些預期結果的了解。 在下列範例中新增強調顯示的那幾行來修正該問題:

/// <summary>
/// Creates a TodoItem.
/// </summary>
/// <param name="item"></param>
/// <returns>A newly created TodoItem</returns>
/// <remarks>
/// Sample request:
///
///     POST /Todo
///     {
///        "id": 1,
///        "name": "Item #1",
///        "isComplete": true
///     }
///
/// </remarks>
/// <response code="201">Returns the newly created item</response>
/// <response code="400">If the item is null</response>
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    await _context.SaveChangesAsync();

    return CreatedAtAction(nameof(Get), new { id = item.Id }, item);
}

Swagger UI 現在清楚地記錄預期的 HTTP 回應碼 (也會顯示 XML 註解):

Swagger UI showing POST Response Class description 'Returns the newly created Todo item' and '400 - If the item is null' for status code and reason under Response Messages.

慣例可作為使用 [ProducesResponseType] 明確裝飾個別動作的替代方案。 如需詳細資訊,請參閱使用 Web API 慣例

Redoc

Redoc 是 Swagger UI 的替代方案。 這是類似的工具,因為其也會使用 OpenAPI 規格來提供 Web API 的文件頁面。 差異在於 Redoc UI 更注重文件,而且不會提供互動式 UI 來測試 API。

若要啟用 Redoc,請將中介軟體新增至 Program.cs

if (app.Environment.IsDevelopment())
{
    // Add OpenAPI 3.0 document serving middleware
    // Available at: http://localhost:<port>/swagger/v1/swagger.json
    app.UseOpenApi();

    // Add web UIs to interact with the document
    // Available at: http://localhost:<port>/swagger
    app.UseSwaggerUi();
    
    // Add ReDoc UI to interact with the document
    // Available at: http://localhost:<port>/redoc
    app.UseReDoc(options =>
    {
        options.Path = "/redoc";
    });
}

執行應用程式並瀏覽至 http://localhost:<port>/redoc,以檢視 Redoc UI:

Redoc documentation for the Sample API.

作者:Christoph NienaberRico SuterDave Brock

檢視或下載範例程式碼 \(英文\) (如何下載)

NSwag 提供下列功能:

  • 能夠運用 Swagger UI 和 Swagger 產生器。
  • 彈性的程式碼產生功能。

使用 NSwag 時,您不需要現有的 API;您可以使用包含 Swagger 的協力廠商 API,然後產生用戶端實作。 NSwag 可讓您加速開發週期,並輕鬆地因應 API 變更進行調整。

註冊 NSwag 中介軟體

註冊 NSwag 中介軟體來:

  • 為實作的 Web API 產生 Swagger 規格。
  • 提供 Swagger UI 以瀏覽並測試 Web API。

若要使用 NSwag ASP.NET Core 中介軟體,請安裝 NSwag.AspNetCore NuGet 套件。 此套件包含用以產生並提供 Swagger 規格、Swagger UI (v2 和 v3) 及 ReDoc UI 的中介軟體。

請使用下列其中一種方法來安裝 NSwag NuGet 套件:

  • 從 [套件管理員主控台] 視窗中:

    • 移至 [檢視]>[其他視窗]>[套件管理員主控台]

    • 瀏覽至 TodoApi.csproj 檔案所在的目錄

    • 執行以下 命令:

      Install-Package NSwag.AspNetCore
      
  • 從 [管理 NuGet 套件] 對話方塊中:

    • 在 [方案總管]>[管理 NuGet 套件] 中,以滑鼠右鍵按一下專案
    • 將 [套件來源] 設定為 "nuget.org"
    • 在搜尋方塊中輸入 "NSwag.AspNetCore"
    • 從 [瀏覽] 索引標籤中選取 "NSwag.AspNetCore" 套件,並按一下 [安裝]

新增和設定 Swagger 中介軟體

請執行下列步驟,以在您的 ASP.NET Core 應用程式中新增及設定 Swagger:

  • Startup.ConfigureServices 方法中,註冊所需的 Swagger 服務:
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TodoContext>(opt =>
        opt.UseInMemoryDatabase("TodoList"));
    services.AddMvc();

    // Register the Swagger services
    services.AddSwaggerDocument();
}
  • Startup.Configure 方法中,啟用中介軟體為產生的 Swagger 規格和 SwaggerUI 提供服務:
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();

    // Register the Swagger generator and the Swagger UI middlewares
    app.UseOpenApi();
    app.UseSwaggerUi3();

    app.UseMvc();
}
  • 啟動應用程式。 瀏覽至:
    • http://localhost:<port>/swagger 以檢視 Swagger UI。
    • http://localhost:<port>/swagger/v1/swagger.json 以檢視 Swagger 規格。

程式碼產生

您可以選擇下列其中一個選項來利用 NSwag 的程式碼產生功能:

使用 NSwagStudio 來產生程式碼

  • 依照 NSwagStudio GitHub 存放庫 \(英文\) 的指示來安裝 NSwagStudio。 在 NSwag 發行頁面上,您可以下載 xcopy 版本,而不需要安裝及管理員權限即可將其啟動。

  • 啟動 NSwagStudio,然後在 [Swagger 規格 URL] 文字方塊中輸入 swagger.json 檔案 URL。 例如: http://localhost:44354/swagger/v1/swagger.json

  • 按一下 [建立本機複本] 按鈕,以產生 Swagger 規格的 JSON 表示法。

    Create local copy of Swagger specification

  • 在 [輸出] 區域中,按一下 [CSharp 用戶端] 核取方塊。 視您的專案而定,您也可以選擇 [TypeScript Client] \(TypeScript 用戶端\)或 [CSharp Web API Controller] \(CSharp Web API 控制器\)。 如果您選取 [CSharp Web API Controller] \(CSharp Web API 控制器\),服務規格會重建服務,作為反向產生。

  • 按一下 [Generate Outputs] \(產生輸出\),以產生 TodoApi.NSwag 專案 的完整 C# 用戶端實作。 若要查看所產生的用戶端程式碼,請按一下 [CSharp Client] \(CSharp 用戶端\) 索引標籤:

//----------------------
// <auto-generated>
//     Generated using the NSwag toolchain v12.0.9.0 (NJsonSchema v9.13.10.0 (Newtonsoft.Json v11.0.0.0)) (http://NSwag.org)
// </auto-generated>
//----------------------

namespace MyNamespace
{
    #pragma warning disable

    [System.CodeDom.Compiler.GeneratedCode("NSwag", "12.0.9.0 (NJsonSchema v9.13.10.0 (Newtonsoft.Json v11.0.0.0))")]
    public partial class TodoClient
    {
        private string _baseUrl = "https://localhost:44354";
        private System.Net.Http.HttpClient _httpClient;
        private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;

        public TodoClient(System.Net.Http.HttpClient httpClient)
        {
            _httpClient = httpClient;
            _settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(() =>
            {
                var settings = new Newtonsoft.Json.JsonSerializerSettings();
                UpdateJsonSerializerSettings(settings);
                return settings;
            });
        }

        public string BaseUrl
        {
            get { return _baseUrl; }
            set { _baseUrl = value; }
        }

        // code omitted for brevity

提示

C# 用戶端程式碼會根據 [Settings] \(設定\) 索引標籤中的選取項目來產生。修改設定以執行工作,例如重新命名預設的命名空間和產生同步方法。

  • 將產生的 C# 程式碼複製到將取用 API 的用戶端專案中檔案。
  • 開始取用 Web API:
 var todoClient = new TodoClient();

// Gets all to-dos from the API
 var allTodos = await todoClient.GetAllAsync();

 // Create a new TodoItem, and save it via the API.
var createdTodo = await todoClient.CreateAsync(new TodoItem());

// Get a single to-do by ID
var foundTodo = await todoClient.GetByIdAsync(1);

自訂 API 文件

Swagger 提供選項來記錄物件模型,以簡化 Web API 的取用作業。

API 資訊與描述

Startup.ConfigureServices 方法中,傳遞至 AddSwaggerDocument 方法的組態動作會新增作者、授權和描述等資訊:

services.AddSwaggerDocument(config =>
{
    config.PostProcess = document =>
    {
        document.Info.Version = "v1";
        document.Info.Title = "ToDo API";
        document.Info.Description = "A simple ASP.NET Core web API";
        document.Info.TermsOfService = "None";
        document.Info.Contact = new NSwag.OpenApiContact
        {
            Name = "Shayne Boyer",
            Email = string.Empty,
            Url = "https://twitter.com/spboyer"
        };
        document.Info.License = new NSwag.OpenApiLicense
        {
            Name = "Use under LICX",
            Url = "https://example.com/license"
        };
    };
});

Swagger UI 會顯示版本資訊:

Swagger UI with version information

XML 註解

若要啟用 XML 註解,請執行下列步驟:

  • 在 [方案總管] 中以滑鼠右鍵按一下專案,然後選取 Edit <project_name>.csproj
  • 將醒目提示的程式碼行手動新增至 .csproj 檔案:
<PropertyGroup>
  <GenerateDocumentationFile>true</GenerateDocumentationFile>
  <NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

資料註解

由於 NSwag 會使用反映,而針對 Web API 動作建議使用的傳回型別是 ActionResult<T>,因此其只能推斷 T 所定義的傳回型別。 您無法自動推斷其他可能的傳回型別。

請考慮下列範例:

[HttpPost]
public ActionResult<TodoItem> Create(TodoItem item)
{
    _context.TodoItems.Add(item);
    _context.SaveChanges();

    return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
}

上述動作會傳回 ActionResult<T>。 在動作內,其會傳回 CreatedAtRoute。 由於控制器具有 [ApiController] 屬性,因此也可能會發生 BadRequest 回應。 如需詳細資訊,請參閱自動 HTTP 400 回應。 請使用資料註解來告知用戶端已知此動作要傳回哪些 HTTP 狀態碼。 使用下列屬性標記動作:

[ProducesResponseType(StatusCodes.Status201Created)]     // Created
[ProducesResponseType(StatusCodes.Status400BadRequest)]  // BadRequest

在 ASP.NET Core 2.2 或更新版本中,您可以使用慣例,而不使用 [ProducesResponseType] 來明確地裝飾個別動作。 如需詳細資訊,請參閱使用 Web API 慣例

Swagger 產生器現在可以正確描述此動作,而產生的用戶端會知道呼叫端點時它們所接收的內容。 建議做法是,使用這些屬性來標記所有動作。

如需 API 動作應該傳回哪些 HTTP 回應的指導方針,請參閱 RFC 9110:HTTP 語意 (第 9.3. 節方法定義)