A Simple Method for Grouping Swagger in ASP.NET Core

2023年8月15日 60点热度 2人点赞 0条评论
内容目录

file

First is the middleware, which determines which groups to display when there is time. All APIs can be obtained from the IApiDescriptionGroupCollectionProvider service, and then identified through APIs to check for groups.

                 if (context.HostingEnvironment.IsDevelopment())
                 {
                     app.UseSwagger();
                     var descriptionProvider = app.ApplicationServices.GetRequiredService<IApiDescriptionGroupCollectionProvider>();
                     app.UseSwaggerUI(options =>
                     {
                         // Default
                         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);
                         }
                     });
                 }

Why configure middleware first instead of services? Because service injection is executed lazily and does not load immediately at startup; the middleware pipeline is loaded first, which determines what list is displayed in the upper right corner.

Next, let's take a look at service injection.

Service injection is divided into two parts: the first part generates the documentation address, and the second part dynamically filters the list of APIs displayed in this document.

    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 = "Default"
                        });
                        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;
            });
        }
    }

First is generating the documentation; we need to place the Controllers without a set GroupName into a default group. Then there's SwaggerGenOptions.DocInclusionPredicate, which can dynamically generate the swagger.json. Since the APIs in the default group do not have a GroupName, we need to check the filtering list, so that the swagger.json accessed by users through different GroupNames is different.

Then directly inject the service:

                 services.AddMySwaggerGen(options =>
                 {
                 });

痴者工良

高级程序员劝退师

文章评论