系列導航及源代碼
需求
在日常開發中,我們需要給前端提供文檔化的API接口定義,甚至需要模擬架設一個fake服務用來調試接口字段。或者對於后端開發人員來說,我們可以通過導入這個接口定義文件到Postman或者其他API客戶端,省去我們手動錄入的麻煩。所以本文就實現如何使用Swagger來管理API接口文檔化。
但是在本文中,我們不涉及關於NSwag的相關內容,通過NSwag,我們甚至可以直接生成前端可以使用的接口定義。關於NSwag的使用方法,請參考:NSwag 和 ASP.NET Core 入門以及官方文檔RicoSuter/NSwag。
目標
實現TodoList
項目的接口文檔化。
原理與思路
在使用IDE或者cli生成新的Web API
項目的時候,項目模版里已經自帶了Swashbuckle.AspNetCore
包用來生成swagger文檔,我們需要使用這個包來實現相關功能。
實現
實現基礎的Swagger API文檔
Program
中極有可能已經添加了SwaggerGen
服務了,我們可以做一點小修改,因為之前我們寫過兩個版本的TodoItemController
,希望將兩個版本也反映到swagger文檔中:
// 省略其他...
builder.Services.AddSwaggerGen(s =>
{
s.SwaggerDoc("1.0", new OpenApiInfo { Title = "TodoList API", Version = "1.0"});
s.SwaggerDoc("2.0", new OpenApiInfo { Title = "TodoList API", Version = "2.0"});
});
中間件的引入我們也可以修改一下:
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(s =>
{
s.SwaggerEndpoint("/swagger/1.0/swagger.json", "TodoList API v1.0");
s.SwaggerEndpoint("/swagger/2.0/swagger.json", "TodoList API v2.0");
});
}
如果在API接口版本控制的那一章我們不是使用的通過更改URL的方式實現的API多版本,那么現在只需要對應版本的Controller上添加:
TodoItemController.cs
[Route("/todo-item")]
[ApiExplorerSettings(GroupName = "1.0")]
[ApiController]
public class TodoItemController : ControllerBase
// 省略其他...
以及
TodoItemV2Controller.cs
[Route("/todo-item")]
[ApiExplorerSettings(GroupName = "2.0")]
[ApiController]
public class TodoItemV2Controller : ControllerBase
// 省略其他...
如果是使用URL路徑實現不同版本API的文檔,可以參考這篇文章的實現:ASP.NET Core 3.1 WebApi Swagger與API版本控制的美妙結合
為Swagger添加認證授權功能
為了添加授權支持,我們可以修改Swagger服務選項如下,增加授權配置:
Program.cs
// 省略其他
s.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Add JWT with Bearer",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
s.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Name = "Bearer",
},
new List<string>()
}
});
此外因為我們需要驗證Issuer和Audience信息,所以需要在Token中攜帶這些信息,這樣Swagger才能授權成功,修改IdentityService
發放Token中獲取Claims的邏輯:
IdentityService.cs
private async Task<List<Claim>> GetClaims()
{
// 演示了返回用戶名和Role兩個claims
var claims = new List<Claim>
{
new(ClaimTypes.Name, User!.UserName),
// 使用fallback去填充這兩個字段,實際項目里可能不需要這樣做
new(JwtRegisteredClaimNames.Iss, _jwtConfiguration.ValidIssuer ?? "TodoListApi"),
new(JwtRegisteredClaimNames.Aud, _jwtConfiguration.ValidAudience ?? "https://localhost:5050")
};
var roles = await _userManager.GetRolesAsync(User);
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
return claims;
}
驗證
啟動Api
項目,打開swagger地址,可以看到API版本選擇,以及授權控制都在界面上有所顯示。
具體的切換查看我就不貼截圖了,大家可以自己試一試。
一點擴展
導入API客戶端
右擊swagger界面上的json文件鏈接選擇另存為,再去對應的API客戶端導入json文件即可。
Postman在這方面做的比較好的是它能夠按照json文件內接口的結構關系生成對應的文件夾結構。
生成fake服務端
可以去這里:Swagger Editor,上傳swagger json文件,選擇生成服務端或者客戶端。
為swagger生成完整的數據定義及API注釋文檔
需要開啟XML注釋功能,為此我們同時需要禁止1591warning(為了避免對所有的方法、類、字段發出沒有xml注釋文檔的警告)。修改項目設置如下:
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>TodoList.Api.xml</DocumentationFile>
<OutputPath></OutputPath>
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>
修改SwaggerGen注入的配置:
TodoList.Api.csproj
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
s.IncludeXmlComments(xmlPath);
我們以CreateTodoList
接口為例去添加xml注釋,
TodoListController.cs
/// <summary>
/// 創建新的TodoList,只有Administrator角色的用戶有此權限
/// </summary>
/// <param name="command">創建TodoList命令</param>
/// <returns></returns>
[HttpPost]
[Authorize(Policy = "OnlyAdmin")]
[ServiceFilter(typeof(LogFilterAttribute))]
public async Task<ApiResponse<Domain.Entities.TodoList>> Create([FromBody] CreateTodoListCommand command)
{
return ApiResponse<Domain.Entities.TodoList>.Success(await _mediator.Send(command));
}
再打開swagger文檔查看,可以看到swagger文檔現在已經有接口說明了:
總結
在本文中我們實現了swagger文檔的生成和一些配置選項的作用,如果需要用到更多OpenAPI相關的特性,推薦熟悉一下NSwag這個組件,它提供了更加強大的功能。
下一篇文章我們實現程序的健康檢查功能。