.NET WebAPI 使用 GroupName 對 Controller 分組呈現 Swagger UI

2022-07-26 12:00:13

在日常開發 webapi 時,我們往往會整合 swagger doc 進行 api 的檔案呈現,當api數量比較多的時候就會導致 swagger ui 上的 api 因為數量太多而顯得雜亂,今天教大家如何利用 GroupName 屬性來對 api 的 Controller 進行分組,然後利用 swagger ui 上的 Select a definition 切換功能進行多組 Controller 的切換。

 

首先進行swagger註冊

            #region 註冊 Swagger
            builder.Services.AddTransient<IConfigureOptions<SwaggerGenOptions>, SwaggerConfigureOptions>();

            builder.Services.AddSwaggerGen(options =>
            {
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{typeof(Program).Assembly.GetName().Name}.xml"), true);

                var modelPrefix = Assembly.GetEntryAssembly()?.GetName().Name + ".Models.";
                options.SchemaGeneratorOptions = new SchemaGeneratorOptions { SchemaIdSelector = type => type.ToString()[(type.ToString().IndexOf("Models.") + 7)..].Replace(modelPrefix, "").Replace("`1", "").Replace("+", ".") };
            });
            #endregion

 

然後啟用 swagger

            #region 啟用 Swagger

            //啟用中介軟體服務生成Swagger作為JSON端點
            app.UseSwagger();

            //啟用中介軟體服務對swagger-ui,指定Swagger JSON端點
            app.UseSwaggerUI(options =>
            {
                var apiDescriptionGroups = app.Services.GetRequiredService<IApiDescriptionGroupCollectionProvider>().ApiDescriptionGroups.Items;
                foreach (var description in apiDescriptionGroups)
                {
                    options.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName);
                }
            });

            #endregion

 

這裡用到了一個自定義的 Swagger Doc 生成設定

    public class SwaggerConfigureOptions : IConfigureOptions<SwaggerGenOptions>
    {
        private readonly IApiDescriptionGroupCollectionProvider provider;


        public SwaggerConfigureOptions(IApiDescriptionGroupCollectionProvider provider) => this.provider = provider;


        public void Configure(SwaggerGenOptions options)
        {
            foreach (var description in provider.ApiDescriptionGroups.Items)
            {
                options.SwaggerDoc(description.GroupName, null);
            }
        }

    }

這個方法的主要作用就是從 ApiDescriptionGroups 進行迴圈依次新增多個 Swagger Doc

 

然後關於本文目的的 swagger 設定就完成了。接下來就是對控制器進行分組標記的操作了。

關於對 Controller 進行 GroupName 分組,這裡需要用到 ApiExplorerSettings 屬性來標記 GroupName,並且同時修改 Route 資訊,新增字首,範例如下

    /// <summary>
    /// 系統存取授權模組
    /// </summary>
    [ApiExplorerSettings(GroupName = "Basic")]
    [Route("Basic/[controller]")]
    [ApiController]
    public class AuthorizeController : ControllerBase
    {

    }

 

這樣就將 AuthorizeController 分到了 Basic 組,在 swagger ui 網頁呈現如下

 

我們可以按照控制器的功能屬性或者業務屬性,將多個控制器分配到一個 Group。

上面講的方法需要對所有的控制器進行新增 [ApiExplorerSettings(GroupName = "xxxxx")] 屬性,下面順便介紹一下如何通過檔案的歸類對 控制器進行批次新增 GroupName

我們可以調整我們的控制器存放為資料夾,將同一個組的控制器放在一個資料夾中,範例如下圖

 

 調整存放路徑之後,利用 vs 的 同步名稱空間功能,選中專案,直接右擊 同步名稱空間,就可以把所有控制器的名稱空間都調整過來,名稱空間的最後一節其實就是我們資料夾的名稱,也就是我們的 GroupName,如下:

 

 

 然後我們可以利用 IControllerModelConvention 在專案啟動時獲取控制器名稱空間的最後一節的值,將他賦值到控制器的 [ApiExplorerSettings(GroupName = "xxxxx")] GroupName 屬性,程式碼如下

    public class GroupNameConvention : IControllerModelConvention
    {
        public void Apply(ControllerModel controller)
        {
            var controllerNamespace = controller.ControllerType.Namespace;
            var groupName = controllerNamespace!.Split('.').LastOrDefault();
            controller.ApiExplorer.GroupName = groupName;
        }
    }

 

然後只要在專案啟動時注入這個方法即可

            builder.Services.AddMvc(options =>
            {
                options.Conventions.Add(new GroupNameConvention());
            });

 

這樣就完成了對 控制器 GroupName 的批次賦值,不過如果想要保持路由字首和 GroupName 一致的話,還是需要自己手動的調整一下 控制器的路由字首。

 

至此 .NET WebAPI 使用 GroupName 對 Controller 分組呈現 Swagger UI 就講解完了,有任何不明白的,可以在文章下面評論或者私信我,歡迎大家積極的討論交流,有興趣的朋友可以關注我目前在維護的一個 .net 基礎框架專案,專案地址如下