ASP.NET Core 进行 swagger 分组的简单方法

2023年8月15日 992点热度 2人点赞 0条评论
内容纲要

file

首先是中间件,它决定了有时间显示哪些分组。
可以从 IApiDescriptionGroupCollectionProvider 服务中获取所有 API,然后通过 API 进行识别,检查是否有分组。

                 if (context.HostingEnvironment.IsDevelopment())
                 {
                     app.UseSwagger();
                     var descriptionProvider = app.ApplicationServices.GetRequiredService<IApiDescriptionGroupCollectionProvider>();
                     app.UseSwaggerUI(options =>
                     {
                         // 默认的
                         options.SwaggerEndpoint($"v1/swagger.json", "v1");
                         foreach (var description in descriptionProvider.ApiDescriptionGroups.Items)
                         {
                             if (description.GroupName == null) continue;
                             options.SwaggerEndpoint($"{description.GroupName}/swagger.json", description.GroupName);
                         }
                     });
                 }

为什么要先配置中间件而不是服务呢。
因为服务注入是延时执行,并不会在程序启动时即加载,最先加载的是中间件管道,中间件管道决定了右上角显示什么列表。

接下来看看服务注入。

服务注入分为两个部分,第一个部分生成文档地址,第二部分是动态筛选这个文档显示的 API 列表。

    public static class SwaggerHelper
    {
        private static readonly HashSet<MethodInfo> Default = new HashSet<MethodInfo>();

        public static void AddMySwaggerGen(this IServiceCollection services, Action<SwaggerGenOptions> setupAction = null)
        {
            services.AddSwaggerGen(options =>
            {
                setupAction.Invoke(options);
                var descriptionProvider = services.BuildServiceProvider().GetRequiredService<IApiDescriptionGroupCollectionProvider>();
                foreach (var description in descriptionProvider.ApiDescriptionGroups.Items)
                {
                    if (description.GroupName == null)
                    {
                        options.SwaggerDoc("v1", new OpenApiInfo
                        {
                            Version = "v1",
                            Title = "v1",
                            Description = "默认"
                        });
                        foreach (var item in description.Items)
                        {
                            if (item.TryGetMethodInfo(out var methodInfo))
                                Default.Add(methodInfo);
                        }
                    }
                    else
                    {
                        options.SwaggerDoc(description.GroupName, new OpenApiInfo
                        {
                            Version = "v1",
                            Title = description.GroupName,
                        });
                    }
                }

                var dir = new DirectoryInfo(AppContext.BaseDirectory);
                var files = dir.GetFiles().Where(x => x.Name.EndsWith(".xml")).ToArray();
                foreach (var item in files)
                {
                    options.IncludeXmlComments(item.FullName);
                }

                options.DoGroups();
            });

        }

        public static void DoGroups(this SwaggerGenOptions swaggerGenOptions)
        {
            // docname == GroupName
            swaggerGenOptions.DocInclusionPredicate((docname, b) =>
            {
                if (!b.TryGetMethodInfo(out MethodInfo methodInfo)) return false;

                if (docname == "v1")
                {
                    return Default.Any(x => x == methodInfo);
                }

                var ver = methodInfo.DeclaringType.GetCustomAttributes(true)
                .OfType<ApiExplorerSettingsAttribute>()
                .FirstOrDefault();

                if (ver == null) return false;
                return b.GroupName == docname;
            });
        }
    }

首先是生成文档,我们需要将没有设置 GroupName 的 Controller 放在一个默认分组中。
然后是 SwaggerGenOptions.DocInclusionPredicate ,可以动态生成 swagger.json,由于默认分组中的 API 没有 GroupName,因此我们需要判断筛选列表,这样用户通过不同的 GroupName 访问的 swagger.json 都是不同的。

然后直接注入服务即可:

                 services.AddMySwaggerGen(options =>
                 {
                 });

痴者工良

高级程序员劝退师

文章评论