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();
  • 启用中间件来提供生成的 OpenApi 规范、Swagger UI 和 Redoc UI,同时在 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();
}
  • 启动应用。 转到:
    • 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 客户端”或“C# Web API 控制器”,具体视项目而定。 如果选中“C# Web API 控制器”,服务规范会重新生成服务,起到反向生成的作用。
  • 单击“生成输出”,以生成 TodoApi.NSwag 项目的完整 C# 客户端实现。 若要查看生成的客户端代码,请单击“C# 客户端”选项卡:
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# 客户端代码的生成依据是,“设置”选项卡中的选择。修改设置以执行任务,例如默认命名空间重命名和同步方法生成。

  • 将生成的 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 warning 预处理程序指令中。 此方法对于不应通过 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] 属性添加到 TodoItem 类的 Name 属性:

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 更侧重于文档,不提供用于测试 API 的交互式 UI。

若要启用 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 规范和 Swagger UI 提供服务:
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 客户端”或“C# Web API 控制器”,具体视项目而定。 如果选中“C# Web API 控制器”,服务规范会重新生成服务,起到反向生成的作用。

  • 单击“生成输出”,以生成 TodoApi.NSwag 项目的完整 C# 客户端实现。 若要查看生成的客户端代码,请单击“C# 客户端”选项卡:

//----------------------
// <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# 客户端代码的生成依据是,“设置”选项卡中的选择。修改设置以执行任务,例如默认命名空间重命名和同步方法生成。

  • 将生成的 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 节 - 方法定义)