Asp.net Core的Swagger接口根據模塊、版本分組


近期一直在學習Asp.net Core,微軟的文檔太難看,都是英文翻譯過來的,很不友好,感謝這個博客,從壹開始前后端分離【 .NET Core2.0 +Vue2.0 】,讓我入門了,剛學到這個Swagger時,我就有個需求,因為我之前寫過的系統是分了不同的模塊,模塊里面再分控制器,不同模塊經常會有相同名稱的控制器,例如銷售中心模塊里有個合同管理控制器,采購中心模塊里也有個合同管理控制器,而且我一個系統接口可能得上百個,那如果都在一個頁面顯示的話,那也太多了,所以我想能不能把接口進行分組。

在博客系統后面也有介紹到Swagger:API多版本控制,帶來的思考,還有網上查到的【dotNet Core】Swagger下簡單的給WebApi分組(我發現網上關於Asp.net Core的資料還是比較少),再結合我自己的需求修改了一下。

先說下我的想法:

定義一個系統分組枚舉Enum,包含我系統所有的控制器分組(或者版本),然后再定義一個特性Attribute,可以接收剛才那個Enum值,在需要分組的控制器類上面定義特性Attribute,Swagger根據系統分組枚舉Enum的值進行分組,將特性Attribute的分組枚舉值一樣的歸為同一個分組,沒有加特性Attribute的歸在無分組下,最終效果如下

 

 

下面是我的代碼,理解為主,不用完全按我寫的

基礎Swagger的用法就不說的,具體可看 從壹開始前后端分離【 .NET Core2.0 +Vue2.0 】這個大師關於Swagger部分的教程,非常適合初級入門

在項目創建一個目錄(ApiGroup),然后創建三個類,分別為ApiGroupAttribute.cs(控制器特性),ApiGroupNames.css(系統分組枚舉),GroupInfoAttribute.cs(給系統分組枚舉值增加相關信息的特性,這個主要是用於在Swagger分組時可關聯Title,Version,Description值)

 

 ApiGroupAttribute.cs代碼如下

using Microsoft.AspNetCore.Mvc.ApiExplorer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ItSys.ApiGroup
{
    /// <summary>
    /// 系統分組特性
    /// </summary>
    public class ApiGroupAttribute : Attribute, IApiDescriptionGroupNameProvider
    {
        public ApiGroupAttribute(ApiGroupNames name)
        {
            GroupName = name.ToString();
        }
        public string GroupName { get; set; }
    }
}

 ApiGroupNames.cs代碼如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ItSys.ApiGroup
{
    /// <summary>
    /// 系統分組枚舉值
    /// </summary>
    public enum ApiGroupNames
    {
        [GroupInfo(Title ="登錄認證",Description ="登錄認證相關接口",Version ="v1")]
        Auth,
        [GroupInfo(Title = "IT", Description = "登錄認證相關接口")]
        It,
        [GroupInfo(Title = "人力資源", Description = "登錄認證相關接口")]
        Hr,
        Cw
    }
}

GroupInfoAttribute.cs代碼如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ItSys.ApiGroup
{
    /// <summary>
    /// 系統模塊枚舉注釋
    /// </summary>
    public class GroupInfoAttribute : Attribute
    {
        public string Title { get; set; }
        public string Version { get; set; }
        public string Description { get; set; }
    }
}

 

打開Startup.cs文件修改ConfigureServices方法(為了方便查看,只列出關於Swagger分組的關鍵代碼)

public void ConfigureServices(IServiceCollection services)
{
    
    #region Swagger
    services.AddSwaggerGen(options =>
    {
        //遍歷ApiGroupNames所有枚舉值生成接口文檔,Skip(1)是因為Enum第一個FieldInfo是內置的一個Int值
        typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
        {
            //獲取枚舉值上的特性
            var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
            options.SwaggerDoc(f.Name, new Swashbuckle.AspNetCore.Swagger.Info
            {
                Title = info?.Title,
                Version = info?.Version,
                Description = info?.Description
            });
        });
        //沒有加特性的分到這個NoGroup上
        options.SwaggerDoc("NoGroup", new Swashbuckle.AspNetCore.Swagger.Info
        {
            Title = "無分組"
        });
        //判斷接口歸於哪個分組
        options.DocInclusionPredicate((docName, apiDescription) =>
        {
            if (docName == "NoGroup")
            {
                //當分組為NoGroup時,只要沒加特性的都屬於這個組
                return string.IsNullOrEmpty(apiDescription.GroupName);
            }
            else
            {
                return apiDescription.GroupName == docName;
            }
        });
}

修改Configure方法

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{

    #region Swagger
    app.UseSwagger();
    app.UseSwaggerUI(options =>
    {
        //遍歷ApiGroupNames所有枚舉值生成接口文檔,Skip(1)是因為Enum第一個FieldInfo是內置的一個Int值
        typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
        {
            //獲取枚舉值上的特性
            var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
            options.SwaggerEndpoint($"/swagger/{f.Name}/swagger.json", info != null ? info.Title : f.Name);

        });
        options.SwaggerEndpoint("/swagger/NoGroup/swagger.json", "無分組");
    });
    #endregion
}

然后你F6生成一下,沒出錯的話,就Ctrl+F5看看,正常的話就會在Swagger右上角看到分組了。

 

 在你需要進行分組的控制器上加上這個分組就ok了

 

目前是一個接口只歸為一個分組,但可能實際中有些公用接口,會出現在多個分組模塊里的,那可以將ApiGroupAttribute增加一個string[]或ApiGroupNames[]屬性,接收多個枚舉值,或者定義多個ApiGroupAttribute特性,不過在ConfigureServices里的Swagger的DocInclusionPredicate分組過濾方法里,就不能單判斷GroupName參數了,可以利用參數ApiDescription反射得出接口控制器上的ApiGroupAttribute特性,獲取所有的ApiGroupNames枚舉值,再進行判斷,實現一個接口可以歸為多個分組。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM