NSwag 和 ASP.NET Core 入门
作者:Christoph Nienaber、Rico Suter 和 Dave 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 14 仅支持 v3 版的 Swagger 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(); // UseSwaggerUI Protected by if (env.IsDevelopment())
}
- 启动应用。 转到:
http://localhost:<port>/swagger
,以查看 Swagger UI。http://localhost:<port>/swagger/v1/swagger.json
,以查看 Swagger 规范。
代码生成
若要利用 NSwag 的代码生成功能,可选择以下选项之一:
- NSwagStudio:一款 Windows 桌面应用,用于在 C# 或 TypeScript 中生成 API 客户端代码。
- NSwag.CodeGeneration.CSharp 或 NSwag.CodeGeneration.TypeScript NuGet 包 - 用于在项目中生成代码。
- 通过命令行使用 NSwag。
- NSwag.MSBuild NuGet 包。
- Unchase OpenAPI (Swagger) Connected Service(Unchase OpenAPI (Swagger) 连接服务):一种 Visual Studio 连接服务,用于在 C# 或 TypeScript 中生成 API 客户端代码。 还可以使用 NSwag 为 OpenAPI 服务生成 C# 控制器。
使用 NSwagStudio 生成代码
- 按照 NSwagStudio GitHub 存储库中的说明操作,以安装 NSwagStudio。 在 NSwag 发布页面上,可以下载无需安装和管理员权限即可启动的 xcopy 版本。
- 启动 NSwagStudio,并在“Swagger 规范 URL”文本框中输入
swagger.json
文件 URL。 例如,http://localhost:5232/swagger/v1/swagger.json
。 - 单击“创建本地副本”按钮,以生成 Swagger 规范的 JSON 表示形式。
- 在“输出”区域中,单击“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 显示版本的信息:
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 注释):
约定可以用作使用 [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(); // UseSwaggerUI is called only in Development.
// 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:
作者:Christoph Nienaber、Rico Suter 和 Dave 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.UseOpenApi();
if (env.IsDevelopment())
{
app.UseSwaggerUi3();
}
app.UseMvc();
}
- 启动应用。 转到:
http://localhost:<port>/swagger
,以查看 Swagger UI。http://localhost:<port>/swagger/v1/swagger.json
,以查看 Swagger 规范。
代码生成
若要利用 NSwag 的代码生成功能,可选择以下选项之一:
- NSwagStudio:一款 Windows 桌面应用,用于在 C# 或 TypeScript 中生成 API 客户端代码。
- NSwag.CodeGeneration.CSharp 或 NSwag.CodeGeneration.TypeScript NuGet 包 - 用于在项目中生成代码。
- 通过命令行使用 NSwag。
- NSwag.MSBuild NuGet 包。
- Unchase OpenAPI (Swagger) Connected Service(Unchase OpenAPI (Swagger) 连接服务):一种 Visual Studio 连接服务,用于在 C# 或 TypeScript 中生成 API 客户端代码。 还可以使用 NSwag 为 OpenAPI 服务生成 C# 控制器。
使用 NSwagStudio 生成代码
按照 NSwagStudio GitHub 存储库中的说明操作,以安装 NSwagStudio。 在 NSwag 发布页面上,可以下载无需安装和管理员权限即可启动的 xcopy 版本。
启动 NSwagStudio,并在“Swagger 规范 URL”文本框中输入
swagger.json
文件 URL。 例如,http://localhost:44354/swagger/v1/swagger.json
。单击“创建本地副本”按钮,以生成 Swagger 规范的 JSON 表示形式。
在“输出”区域中,单击“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 显示版本的信息:
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 节 - 方法定义)。