ASP.NET Core Web API Swagger 按标签Tags分组排序显示原创
金蝶云社区-云社区用户26064194
云社区用户26064194
7人赞赏了该文章 935次浏览 未经作者许可,禁止转载编辑于2023年03月15日 15:04:07
summary-icon摘要由AI智能服务提供

本文介绍了如何在ASP.NET Core Web API的Swagger中按标签(Tags)分组并排序显示接口,同时处理未打标签的接口归为"未分组"类别,以及分组内按接口路径排序的实现方法。通过为Controller或Action打上TagsAttribute特性,使用自定义的TagReorderDocumentFilter过滤器来清空并重新添加Tags,并按汉字拼音排序。此外,未打标签的接口被默认归类到"未分组"。配置Swagger时通过TagActionsBy和OrderActionsBy方法实现分组和排序功能。文章还提到在Linux系统中遇到的中文拼音排序问题及其解决方案,以及多标签接口排序的复杂性及处理方法。

ASP.NET Core Web API Swagger 按标签Tags分组排序显示

需求

  1. swagger页面按标签Tags分组显示。

  2. 没有打标签Tags的接口,默认归到"未分组"。

  3. 分组内按接口路径排序

说明

为什么没有使用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);

效果图

分组按汉字拼音排序,分组内按接口路径排序

在实现过程中遇到的问题

  1. 部署到linux系统,中文拼音排序问题,不想修改linux系统配置,于是修改代码,通过TinyPinyin.Net库实现。

  2. 分组排序和分组内接口排序问题
    一个接口可以打多个标签。如果是单个标签,可以通过OrderActionsBy对分组和接口同时排序。如果是多个标签,则无法通过OrderActionsBy对分组和接口同时排序,只能对接口进行排序。
    可以在TagReorderDocumentFilter过滤器中对标签进行排序,但Tags中都是controller默认的标签,所以要先清空,再重新添加,然后再排序。

为了解决这些问题,提供一个容易阅读和查找的swagger文档目录,断断续续花费了很长时间才算解决。


图标赞 7
7人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!