外掛化程式設計之WebAPI統一返回模型

2022-10-09 15:00:48
WebApi返回資料我們一般包裹在一個公共的模型下面的,而不是直接返回最終資料,在返回引數中,顯示出當前請求的時間戳,是否請求成功,如果錯誤那麼錯誤的訊息是什麼,狀態碼(根據業務定義的值)等等。我們常規的返回值常需要如下欄位,為此我們可以先定義IResultDto 介面
/// <summary>
    /// 結果模型
    /// </summary>
    public interface IResultDto
    {
        /// <summary>
        /// 成功
        /// </summary>
        bool Successful { get; set; }

        /// <summary>
        /// 返回標識碼
        /// </summary>
        int Code { get; set; }

        /// <summary>
        /// 操作碼(用於冪等性驗證,每次請求都會返回一個新的,以便使用者下次更新使用)
        /// </summary>
        string OpCode { get; set; }

        /// <summary>
        /// 訊息
        /// </summary>
        string Msg { get; set; }


        /// <summary>
        /// 常規資料
        /// </summary>
        dynamic Data { get; set; }

    }

/// <summary>
    /// 結果模型
    /// </summary>
    public interface IResultDto
    {
        /// <summary>
        /// 成功
        /// </summary>
        bool Successful { get; set; }

        /// <summary>
        /// 返回標識碼
        /// </summary>
        int Code { get; set; }

        /// <summary>
        /// 操作碼(用於冪等性驗證,每次請求都會返回一個新的,以便使用者下次更新使用)
        /// </summary>
        string OpCode { get; set; }

        /// <summary>
        /// 訊息
        /// </summary>
        string Msg { get; set; }


        /// <summary>
        /// 常規資料
        /// </summary>
        dynamic Data { get; set; }

    }

   對應的還介面的實現如下,為了更好的獨立性,在這裡實現了成功和失敗賦值方法。

/// <summary>
    /// 返回模型
    /// </summary>
    public class ResultDto : IResultDto
    {
        /// <summary>
        /// 返回標識碼
        /// </summary>
        public int Code { get; set; }

        /// <summary>
        /// 成功
        /// </summary>
        [JsonIgnore]
        public bool Successful { get; set; }

        /// <summary>
        /// 訊息
        /// </summary>
        public string Msg { get; set; }


        /// <summary>
        /// 操作碼(用於冪等性驗證,每次請求都會返回一個新的,以便使用者下次更新使用)
        /// </summary>
        public string OpCode { get; set; }

        /// <summary>
        /// 常規資料
        /// </summary>
        public dynamic Data { get; set; }


        /// <summary>
        /// 成功
        /// </summary>
        /// <returns></returns>
        public ResultDto Success(string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto Success(dynamic data = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto Success(dynamic data = default, dynamic data2 = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 失敗
        /// </summary>
        /// <param name="code"></param>
        /// <param name="msg">說明</param>
        public ResultDto Failed(int code = default, string msg = "failed")
        {
            this.Code = code;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }


    }

/// <summary>
    /// 返回模型
    /// </summary>
    public class ResultDto : IResultDto
    {
        /// <summary>
        /// 返回標識碼
        /// </summary>
        public int Code { get; set; }

        /// <summary>
        /// 成功
        /// </summary>
        [JsonIgnore]
        public bool Successful { get; set; }

        /// <summary>
        /// 訊息
        /// </summary>
        public string Msg { get; set; }


        /// <summary>
        /// 操作碼(用於冪等性驗證,每次請求都會返回一個新的,以便使用者下次更新使用)
        /// </summary>
        public string OpCode { get; set; }

        /// <summary>
        /// 常規資料
        /// </summary>
        public dynamic Data { get; set; }


        /// <summary>
        /// 成功
        /// </summary>
        /// <returns></returns>
        public ResultDto Success(string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto Success(dynamic data = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto Success(dynamic data = default, dynamic data2 = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 失敗
        /// </summary>
        /// <param name="code"></param>
        /// <param name="msg">說明</param>
        public ResultDto Failed(int code = default, string msg = "failed")
        {
            this.Code = code;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }


    }

 我們嘗試返回該型別結果

 return ResultTo.Success(tokenDto, "登入成功");

 通過swagger檔案我們看下返回效果

  細心的你是不是發現了啥,我們的介面檔案他不認識我們返回型別的實體呀,還玩啥,別急我們可以再稍微擴充套件下,加個泛型的返回,看起來就完美了。

   /// <summary>
    /// 泛型結果模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IResultDto<T> : IResultDto  
    {
        /// <summary>
        /// 常規資料
        /// </summary>
        new T Data { get; set; }

    }

    /// <summary>
    /// 泛型結果模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IResultDto<T> : IResultDto  
    {
        /// <summary>
        /// 常規資料
        /// </summary>
        new T Data { get; set; }

    }

我們實現泛型介面如下,同樣在這裡實現了成功和失敗賦值方法。

/// <summary>
    /// 泛型類 返回模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ResultDto<T> : ResultDto, IResultDto<T>
    {
        /// <summary>
        /// 常規資料
        /// </summary>
        public new T Data { get; set; }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto<T> Success(T data = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }


        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto<T> Failed(string msg = "err")
        {
            this.Code = (int)EnumCode.Err;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto<T> Failed(string msg, int enumCode)
        {
            this.Code = enumCode;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }


    }

/// <summary>
    /// 泛型類 返回模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ResultDto<T> : ResultDto, IResultDto<T>
    {
        /// <summary>
        /// 常規資料
        /// </summary>
        public new T Data { get; set; }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto<T> Success(T data = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }


        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto<T> Failed(string msg = "err")
        {
            this.Code = (int)EnumCode.Err;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultDto<T> Failed(string msg, int enumCode)
        {
            this.Code = enumCode;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }


    }

我們再次嘗試返回該型別結果

  return ResultTo<TokenDto>.Success(tokenDto, "登入成功");

看看swagger檔案的顯示,正是我們需要的

 根據經驗我們還要需要返回列表

 /// <summary>
    /// 泛型結果模型集合
    /// </summary>
    public interface IResultListDto<T> : IResultDto  
    {

        /// <summary>
        /// 常規資料
        /// </summary>
        new List<T> Data { get; set; }

    }

 /// <summary>
    /// 泛型結果模型集合
    /// </summary>
    public interface IResultListDto<T> : IResultDto  
    {

        /// <summary>
        /// 常規資料
        /// </summary>
        new List<T> Data { get; set; }

    }
 /// <summary>
    /// 泛型類 返回模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ResultListDto<T> : ResultDto, IResultListDto<T>  
    {

        /// <summary>
        /// 常規資料
        /// </summary>
        public new List<T> Data { get; set; }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultListDto<T> Success(List<T> data = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }


        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultListDto<T> Failed(string msg = "err")
        {
            this.Code = (int)EnumCode.Err;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultListDto<T> Failed(string msg, int enumCode)
        {
            this.Code = enumCode;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }


    }

    /// <summary>
    /// 泛型類 返回模型
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ResultListDto<T> : ResultDto, IResultListDto<T>  
    {

        /// <summary>
        /// 常規資料
        /// </summary>
        public new List<T> Data { get; set; }

        /// <summary>
        /// 成功
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultListDto<T> Success(List<T> data = default, string msg = "success")
        {
            this.Code = (int)EnumCode.Succeed;
            this.Successful = true;
            this.Data = data;
            this.Msg = msg;
            return this;
        }


        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultListDto<T> Failed(string msg = "err")
        {
            this.Code = (int)EnumCode.Err;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }

        /// <summary>
        /// 異常
        /// </summary>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public ResultListDto<T> Failed(string msg, int enumCode)
        {
            this.Code = enumCode;
            this.Successful = false;
            this.Msg = msg;
            return this;
        }


    }

順著這個思路,我們可以繼續實現分頁,多引數返回等等,如果你覺得麻煩,當然也可以直接在nuget直接參照 Sy.ResultExtension,這個元件,苦逼的碼農小哥已經為你實現了該功能。