需求
- swagger頁面按標籤Tags分組顯示。
- 沒有打標籤Tags的介面,預設歸到"未分組"。
- 分組內按介面路徑排序
說明
為什麼沒有使用GroupName對介面進行分組?
暫時不需要,以及不想點選swagger頁面右上角那個下拉框。
當然Tags和GroupName不衝突,不影響透過GroupName再分組顯示。
如何實現
1. 為controller或action打上標籤
TagsAttribute特性可以打在controller類上,也可以打在action方法上,一個類或方法上可以打多個標籤。示例:
[Tags("標籤1", "標籤2")]
有個小坑,Tags要麼打在controller上,要麼打在action上,不能同時打。
2. 實現IDocumentFilter介面
清空原有的Tags,並按介面類或方法上的標籤重新新增Tags,然後排序。
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Utils;
namespace DotnetDatamining.Filters
{
/// <summary>
/// Workaround for https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2162
/// When adding XML controller descriptions to the swagger description document,
/// controllers are listed out of alphabetical order.
///
/// This filter explicitly reorders them.
/// </summary>
public class TagReorderDocumentFilter : IDocumentFilter
{
/// <summary>
/// Allows customization of the swagger description document
/// </summary>
/// <param name="swaggerDoc">The generated swagger description document</param>
/// <param name="context">Context information</param>
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Tags.Clear(); //清空Tags
//重新新增Tags
foreach (var path in swaggerDoc.Paths)
{
foreach (var o in path.Value.Operations)
{
foreach (var tag in o.Value.Tags)
{
swaggerDoc.Tags.Add(tag);
}
}
}
//排序
swaggerDoc.Tags = swaggerDoc.Tags
.OrderBy(tag => TinyPinYinUtil.GetPinYin(tag.Name)) //按漢字拼音排序
.ToList();
}
}
}
3. Swagger配置
//swagger配置
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "XXX",
Version = "1.0",
Description = "XXX"
});
var path = Path.Combine(AppContext.BaseDirectory, "DotnetDatamining.xml"); // xml文件絕對路徑
c.IncludeXmlComments(path, true); // 顯示控制器層註釋
c.TagActionsBy(a =>
{
var tagAttr = a.ActionDescriptor.EndpointMetadata.OfType<TagsAttribute>().FirstOrDefault();
if (tagAttr != null)
{
return tagAttr.Tags.ToList();
}
return new List<string>() { "未分組" };
});
c.DocumentFilter<TagReorderDocumentFilter>(); // Workaround: After adding XML controller descriptions, they are listed out of alphabetical order
c.OrderActionsBy(a => a.RelativePath); // 對Action排序
});
上述程式碼說明
(1) 使用TagReorderDocumentFilter過濾器
c.DocumentFilter<TagReorderDocumentFilter>();
(2) 對Action按標籤分組
沒有打標籤Tags的介面,預設歸到"未分組"。
c.TagActionsBy(a =>
{
var tagAttr = a.ActionDescriptor.EndpointMetadata.OfType<TagsAttribute>().FirstOrDefault();
if (tagAttr != null)
{
return tagAttr.Tags.ToList();
}
return new List<string>() { "未分組" };
});
(2) 分組內對Action按介面路徑排序
c.OrderActionsBy(a => a.RelativePath);
效果圖
分組按漢字拼音排序,分組內按介面路徑排序
在實現過程中遇到的問題
- 部署到linux系統,中文拼音排序問題,不想修改linux系統配置,於是修改程式碼,透過TinyPinyin.Net庫實現。
- 分組排序和分組內介面排序問題
一個介面可以打多個標籤。如果是單個標籤,可以透過OrderActionsBy對分組和介面同時排序。如果是多個標籤,則無法透過OrderActionsBy對分組和介面同時排序,只能對介面進行排序。
可以在TagReorderDocumentFilter過濾器中對標籤進行排序,但Tags中都是controller預設的標籤,所以要先清空,再重新新增,然後再排序。
為了解決這些問題,提供一個容易閱讀和查詢的swagger文件目錄,斷斷續續花費了很長時間才算解決。