4

插件化编程之WebAPI统一返回模型 - noert

 1 year ago
source link: https://www.cnblogs.com/noert/p/16771697.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

插件化编程之WebAPI统一返回模型

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 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文档我们看下返回效果

376827-20221009114556531-761314198.png

  细心的你是不是发现了啥,我们的接口文档他不认识我们返回类型的实体呀,还玩啥,别急我们可以再稍微扩展下,加个泛型的返回,看起来就完美了。

   /// <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;
        }


    }

我们再次尝试返回该类型结果

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

看看swagger文档的显示,正是我们需要的

376827-20221009115123239-1756986297.png

 根据经验我们还要需要返回列表

 /// <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;
        }


    }

顺着这个思路,我们可以继续实现分页,多参数返回等等,如果你觉得麻烦,当然也可以直接在nuget直接引用 Sy.ResultExtension,这个组件,苦逼的码农小哥已经为你实现了该功能。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK