非常喜歡. NET 的 ///
註釋,寫代碼的時候就順道完成寫文檔的過程,簡直不要太爽了。 ASP. NET CORE 也是一樣的,通過 Swagger
工具,可以自動生成 API 的接口文檔(OpenAPI規範),提供給前端使用,也可以用過 APIPOST/APIFOX 之類的工具提供給前端同學直接調用。
生成 OpenAPI 註釋
只需要安裝 swashbuckle.aspnetcore
包,在項目上設置生成 XML 格式的註釋,並且如下配置即可自動生成 OpenAPI 的文檔,對我這個例子,可以通過 swagger/v{version}/swagger.json
訪問。
services.AddSwaggerGen(options =>
{
// options.CustomSchemaIds(type => type.AssemblyQualifiedName);
var fileName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
var filePath = Path.Combine(AppContext.BaseDirectory, fileName);
// integrate xml comments
options.IncludeXmlComments(filePath);
});
app.UseSwagger();
app.UseSwaggerUI(
options =>
{
foreach (var description in app.DescribeApiVersions())
{
var url = $"/swagger/{description.GroupName}/swagger.json";
var name = description.GroupName.ToUpperInvariant();
options.SwaggerEndpoint(url, name);
}
});
註釋如下:
/// <summary>
/// 這個接口
/// </summary>
public class CoverageDataController : ODataController
{
/// <summary>
/// 獲取蓋度數據
/// </summary>
/// <param name="key"></param>
/// <param name="options"></param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType(typeof(CoverageDataDto), Status200OK)]
public async Task<IActionResult> Get(string key, ODataQueryOptions<CoverageDataDto> options)
{
}
}
生成 Tags 註釋
在使用 APIFOX 導入 swagger.json
導入時,我發現,對每一個 path 的註釋能夠正常顯示,但是對的控制器的註釋不能正常被識別。
查看生成的 swagger.json
,這個 CoverageData 被解釋成了 OpenAPI 的 Tags,那對應控制器的相關注釋,是需要使用另外的標註實現的,而不能直接使用///的註釋實現。
paths": {
"/api/v{version}/CoverageData({key})": {
"get": {
"tags": [
"CoverageData"
],
"summary": "獲取蓋度數據",
安裝的新的包 swashbuckle.aspnetcore.annotations
,然後增加啓用語句,如下:
services.AddSwaggerGen(options =>
{
// options.CustomSchemaIds(type => type.AssemblyQualifiedName);
var fileName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
var filePath = Path.Combine(AppContext.BaseDirectory, fileName);
// integrate xml comments
options.IncludeXmlComments(filePath);
options.EnableAnnotations();
});
在控制器的聲明上面,添加 [SwaggerTag("接受蓋度數據")]
註解:
/// <summary>
/// 這個接口
/// </summary>
[SwaggerTag("接受蓋度數據")]
public class CoverageDataController : ODataController
{
}
最後生成的 swagger.json
文件在末尾多了幾行:
"tags": [
{
"name": "CoverageData",
"description": "接受蓋度數據"
}
]
Swagger 裏面就可以看到註釋了:
但是導入到 APIFOX 中,顯示的組別名稱依然是 CoverageData ,沒有達到我想要的效果,我想將其替換成可以顯示友好的名稱。實質上是爲 CoverageData 取一個別名。
注:這種方法不能與 swagger 配置的 TagActionsBy 方法的一起使用。
Tags 註解
在 ASP. NET CORE 中,可以在控制器上使用 [Tags("蓋度接口")]
,對控制器的組別進行標註。這樣生成的 tag 名稱直接就換成了的中文名稱。
"paths": {
"/api/v{version}/CoverageData({key})": {
"get": {
"tags": [
"蓋度接口"
],
"summary": "獲取蓋度數據",
....
"tags": [
{
"name": "CoverageData",
"description": "接受蓋度數據"
}
]
但是 swagger 變得非常奇怪:
出現了兩個不同的 tag,其中 CoverageData 名稱的下面沒有從屬的 api。
如果沒有對 Tag 寫 description 的要求,那麼使用這個方案是最簡單的:設置[Tags],不要設置[SwaggerTag]。
DisplayName 註解
這麼看應該是通過 swagger 生成的 tag 與通過 [Tags]
註解生成的 tag 對象不能匹配,導致 swagger 生成的沒用被引用。
查了很久資料,說這個是一個現在的 Bug,有人通過重寫 DisplayName,在帖子中給了臨時的解決方案:
- 先增加一個新的類型。
/// <summary>
/// Uses the [DisplayName] attribute as the Controller name in OpenAPI spec and Swagger/ReDoc UI if available else the default Controller name.
/// </summary>
public class ControllerDocumentationConvention : IControllerModelConvention
{
void IControllerModelConvention.Apply(ControllerModel controller)
{
if (controller == null)
{
return;
}
foreach (var attribute in controller.Attributes)
{
if (attribute is DisplayNameAttribute displayNameAttribute && !string.IsNullOrWhiteSpace(displayNameAttribute.DisplayName))
{
controller.ControllerName = displayNameAttribute.DisplayName;
}
}
}
}
- 給 Controller 配置這個命名轉換。
services.AddControllers(o =>
{
o.Conventions.Add(new ControllerDocumentationConvention());
});
- 在需要調整名稱的控制器上添加
[DisplayName("targetNames")]
即可。可以看到名稱與註釋都得到的保留,最終效果如下:
導入 APIFOX 也可以正常識別了。
參考資料
- swagger ui - How to provide OpenAPI 'tag' group descriptions for a .NET Core 7 minimal API? - Stack Overflow
- TagActionsBy custom tag or controller name · Issue #467 · domaindrivendev/Swashbuckle.AspNetCore (github.com)
- Support for associating XML Comments with custom tags defined using TagsAttribute by yingxinj · Pull Request #2565 · domaindrivendev/Swashbuckle.AspNetCore (github.com)