在日常開發 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 一致的話,還是需要自己手動的調整一下 控制器的路由字首。