概述

OpenApi概述

  OpenAPI 规范(以前称为 Swagger 规范)是 REST API 的 API 描述格式。 OpenAPI 文件允许您描述整个 API,包括:

  • 可用端点 ( /users ) 以及每个端点上的操作 ( GET /users , POST /users )
  • 操作参数 每个操作的输入和输出
  • 认证方式
  • 联系信息、许可证、使用条款和其他信息。

  API规范可以用YAML或JSON编写。该格式对于人类和机器来说都很容易学习和阅读。完整的 OpenAPI 规范可以在 GitHub 上找到: OpenAPI 3.0 规范

Swagger概述

  Swagger是一组围绕 OpenAPI 规范构建的开源工具,可以帮助您设计、构建、记录和使用 REST API。主要的 Swagger 工具包括:

  • Swagger Editor – 基于浏览器的编辑器,您可以在其中编写 OpenAPI 定义。
  • Swagger UI – 将 OpenAPI 定义呈现为交互式文档。
  • Swagger Codegen – 根据 OpenAPI 定义生成服务器存根和客户端库。
  • Swagger Editor Next ——基于浏览器的编辑器,您可以在其中编写和查看
  • Swagger Core – 用于创建、使用和使用 OpenAPI 定义的相关库。
  • Swagger Parser – 用于解析 OpenAPI 定义的独立库
  • Swagger APIDom – 提供单一、统一的结构,用于跨各种描述语言和序列化格式描述 API。

  Swagger (OpenAPI) 是一个与语言无关的规范,用于描述 REST API。 它使计算机和用户无需直接访问源代码即可了解 REST API 的功能。 其主要目标是:

  • 尽量减少连接分离的服务所需的工作量。
  • 减少准确记录服务所需的时间。

.NET 的两个主要 OpenAPI 实现是 SwashbuckleNSwag

Swashbuckle

  Swashbuckle 有三个主要组件:

  • Swashbuckle.AspNetCore.Swagger:将 SwaggerDocument 对象公开为 JSON 终结点的 Swagger 对象模型和中间件。
  • Swashbuckle.AspNetCore.SwaggerGen:从路由、控制器和模型直接生成 SwaggerDocument 对象的 Swagger 生成器。 它通常与 Swagger 终结点中间件结合,以自动公开 Swagger JSON。
  • Swashbuckle.AspNetCore.SwaggerUI:Swagger UI 工具的嵌入式版本。 它解释 Swagger JSON 以构建描述 Web API 功能的可自定义的丰富体验。 它包括针对公共方法的内置测试工具。

Nuget包安装

  只需要安装Swashbuckle.AspNetCore库即可,其依赖于Swashbuckle.AspNetCore.SwaggerSwashbuckle.AspNetCore.SwaggerGenSwashbuckle.AspNetCore.SwaggerUI

1
Install-Package Swashbuckle.AspNetCore

配置Swagger中间件

  1. 添加Swagger服务
1
2
3
4
builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer(); // 适用于最小API
builder.Services.AddSwaggerGen();
  1. 启用Swagger服务
1
2
3
4
5
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
  1. 启动应用程序导航到https://localhost:<port>/swagger,找到 Swagger UI。 通过 Swagger UI 浏览 API

Swagger自定义配置

添加API信息和说明

  通过 SwaggerGen 配置 Swagger 文档的元信息,如版本、标题、描述、服务条款、联系人信息和许可协议。这些元信息会显示在 Swagger UI 界面中,帮助开发者或 API 使用者理解 API 的使用和相关的法律信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
builder.Services.AddSwaggerGen(options =>
{
// SwaggerDoc此方法用于为生成的 Swagger 文档创建新的 API 文档版本
options.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1", // API 文档的版本号
Title = "SwaggerDemo API", // 文档的标题
Description = "An Test Project", // 对 API 的简短描述
TermsOfService = new Uri("https://example.com/terms"), // API 的服务条款。这个属性通常是一个链接,指向项目的服务条款页面。开发者可以将用户引导到该页面了解如何使用 API。
Contact = new OpenApiContact //提供有关 API 的联系信息
{
Name = "Example Contact", // 联系人的名字。可以是个人的名字,也可以是负责 API 的团队或公司的名字。
Url = new Uri("https://example.com/contact") // 联系人的链接。通常是指向联系页面或者开发团队的联系方式页面。
},
License = new OpenApiLicense // 用于描述 API 的许可信息
{
Name = "Example License", // API 的许可名称。通常指定 API 的使用协议,如 MIT、Apache License 2.0 等。
Url = new Uri("https://example.com/license") // 许可的链接。可以指向完整的许可条款文本。
}
});
});

添加XML注释

  1. 打开项目文件<project_name>.csproj,添加如下内容:
1
2
3
4
5
6
<PropertyGroup>
<!-- 生成XML文档 -->
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<!-- 在项目范围内取消未注释的公共类型和成员取消警告 -->
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
  1. 添加注释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <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);
}

数据注释

  使用 System.ComponentModel.DataAnnotations 命名空间中找到的属性来标记模型,以帮助驱动 Swagger UI 组件。

  将 [Required] 属性添加到 TodoItem 类的 Name 属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace SwashbuckleSample.Models;

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

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

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

  将 [Produces("application/json")] 属性添加到 API 控制器。 这样做的目的是声明控制器的操作支持 application/json 的响应内容类型:

1
2
3
4
5
6
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoController : ControllerBase
{
}

  “媒体类型”下拉列表选此内容类型作为控制器的默认 GET 操作:

描述响应类型

  使用 Web API 的开发人员最关心的问题是返回的内容,特别是响应类型和错误代码(如果不标准)。 在 XML 注释和数据注释中表示响应类型和错误代码。

  Create 操作成功后返回 HTTP 201 状态代码。 发布的请求正文为 NULL 时,将返回 HTTP 400 状态代码。 如果 Swagger UI 中没有提供合适的文档,那么使用者会缺少对这些预期结果的了解。 在以下示例中,通过添加突出显示的行解决此问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <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响应代码:

自定义UI

  默认 UI 既实用又可呈现。 但是,API 文档页应代表品牌或主题。 将 Swashbuckle 组件标记为需要添加资源以提供静态文件,并构建文件夹结构以托管这些文件。

  1. 启用静态文件中间件:
1
2
3
app.UseHttpsRedirection();
app.UseStaticFiles();
app.MapControllers();
  1. 若要插入其他 CSS 样式表,请将其添加到项目的 wwwroot 文件夹中,并在中间件选项中指定相对路径:
1
2
3
4
5
6
7
if (app.Environment.IsDevelopment())
{
app.UseSwaggerUI(options => // UseSwaggerUI is called only in Development.
{
options.InjectStylesheet("/swagger-ui/custom.css");
});
}
Knife4jUI库
  1. 安装Nuget包
1
Install-Package IGeekFan.AspNetCore.Knife4jUI
  1. 配置使用Knife4jUI
1
2
3
4
5
6
7
8
9
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseKnife4UI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
options.RoutePrefix = string.Empty;
});
}

授权认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
builder.Services.AddSwaggerGen(options =>
{
// others

// 添加 Bearer Token 到 Swagger 文档中
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "输入 Bearer [space] 然后是你的 Token。示例: 'Bearer abc123def456'",
});

// 让 Swagger 默认需要 Bearer Token
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});

设置Swagger

设置OpenAPI版本

  默认情况下,Swashbuckle 会在 3.0 版规范(官方称为 OpenAPI 规范)中生成并公开 Swagger JSON。 为了支持向后兼容性,可以改为选择以 2.0 格式公开 JSON。 对于当前支持 OpenAPI 版本 2.0 的 Microsoft Power Apps 和 Microsoft Flow 等集成,此 2.0 格式非常重要。 若要选择采用 2.0 格式,请在 Program.cs 中设置 SerializeAsV2 属性:

1
2
3
4
app.UseSwagger(options =>
{
options.SerializeAsV2 = true;
});

设置SwaggerUI

设置总结点地址

  如果使用目录及 IIS 或反向代理,请使用 ./ 前缀将 Swagger 终结点设置为相对路径。 例如 ./swagger/v1/swagger.json。 使用 /swagger/v1/swagger.json 指示应用在 URL 的真实根目录中查找 JSON 文件(如果使用,加上路由前缀)。

1
2
3
4
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json","v1");
});
设置路由前缀

  默认的路由前缀为swagger,通过http://localhost:5000/swagger访问SwaggerUI,可通过RoutePrefix属性修改默认路由前缀,同时需要指定Swagger总结点swagger.json文件的路径

1
2
3
4
5
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json","v1");
options.RoutePrefix = string.Empty;
});
折叠Api
1
2
3
4
app.UseSwaggerUI(options =>
{
options.DocExpansion(DocExpansion.None);
});
隐藏Model
1
2
3
4
app.UseSwaggerUI(options =>
{
options.DefaultModelsExpandDepth(-1);
});