基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型

转载于:https://github.com/Meowv/Blog

在实际开发过程中,每个公司可能不尽相同,但都大同小异,我们的返回数据都是包裹在一个公共的模型下面的,而不是直接返回最终数据,在返回参数中,显示出当前请求的时间戳,是否请求成功,如果错误那么错误的消息是什么,状态码(状态码可以是我们自己定义的值)等等。可能显得很繁琐,没必要,但这样做的好处毋庸置疑,除了美化了我们的API之外,也方便了前端同学的数据处理。

我们将统一的返回模型放在.ToolKits层中,之前说过这里主要是公共的工具类、扩展方法。

新建一个Base文件夹,添加响应实体类ServiceResult.cs,在Enum文件夹下单独定义一个ServiceResultCode响应码枚举,0/1。分别代表 成功和失败。

//ServiceResultCode.cs
namespace Meowv.Blog.ToolKits.Base.Enum
{
///
/// 服务层响应码枚举
///
public enum ServiceResultCode
{
///
/// 成功
///
Succeed = 0,

    /// <summary>/// 失败/// </summary>Failed = 1,
}

}
//ServiceResult.cs
using Meowv.Blog.ToolKits.Base.Enum;
using System;

namespace Meowv.Blog.ToolKits.Base
{
///
/// 服务层响应实体
///
public class ServiceResult
{
///
/// 响应码
///
public ServiceResultCode Code { get; set; }

    /// <summary>/// 响应信息/// </summary>public string Message { get; set; }/// <summary>/// 成功/// </summary>public bool Success => Code == ServiceResultCode.Succeed;/// <summary>/// 时间戳(毫秒)/// </summary>public long Timestamp { get; } = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000;/// <summary>/// 响应成功/// </summary>/// <param name="message"></param>/// <param name="data"></param>/// <returns></returns>public void IsSuccess(string message = ""){Message = message;Code = ServiceResultCode.Succeed;}/// <summary>/// 响应失败/// </summary>/// <param name="message"></param>/// <param name="data"></param>/// <returns></returns>public void IsFailed(string message = ""){Message = message;Code = ServiceResultCode.Failed;}/// <summary>/// 响应失败/// </summary>/// <param name="exexception></param>/// <param name="data"></param>/// <returns></returns>public void IsFailed(Exception exception){Message = exception.InnerException?.StackTrace;Code = ServiceResultCode.Failed;}
}

}
可以看到,还定义了 string 类型的 Message,bool 类型的 Success,Success取决于Code == ServiceResultCode.Succeed的结果。还有一个当前的时间戳Timestamp。

其中还有IsSuccess(…)和IsFailed(…)方法,当我们成功返回数据或者当系统出错或者参数异常的时候执行,这一点也不难理解吧。

这个返回模型暂时只支持无需返回参数的api使用,还需要扩展一下,当我们需要返回其它各种复杂类型的数据就行不通了。所以还需要添加一个支持泛型的返回模型,新建模型类:ServiceResultOfT.cs,这里的T就是我们的返回结果,然后继承我们的ServiceResult,指定T为class。并重新编写一个IsSuccess(…)方法,代码如下:

//ServiceResultOfT.cs
using Meowv.Blog.ToolKits.Base.Enum;

namespace Meowv.Blog.ToolKits.Base
{
///
/// 服务层响应实体(泛型)
///
///
public class ServiceResult : ServiceResult where T : class
{
///
/// 返回结果
///
public T Result { get; set; }

    /// <summary>/// 响应成功/// </summary>/// <param name="result"></param>/// <param name="message"></param>public void IsSuccess(T result = null, string message = "")

{
Message = message;
Code = ServiceResultCode.Succeed;
Result = result;
}
}
}
此时针对无需返回参数和需要返回参数的api都可以满足要求了。但是还有一种就没办法了,那就是带分页的数据,我们都应该知道想要分页,数据总数肯定是必不可少的。

所以此时还需要扩展一个分页的响应实体,当我们使用的时候,直接将分页响应实体作为上面写的ServiceResult中的T参数,即可满足需求。

新建文件夹Paged,添加总数接口IHasTotalCount、返回结果列表接口IListResult

//IHasTotalCount.cs
namespace Meowv.Blog.ToolKits.Base.Paged
{
public interface IHasTotalCount
{
///
/// 总数
///
int Total { get; set; }
}
}

//IListResult.cs
using System.Collections.Generic;

namespace Meowv.Blog.ToolKits.Base.Paged
{
public interface IListResult
{
///
/// 返回结果
///
IReadOnlyList Item { get; set; }
}
}
IListResult接受一个参数,并将其指定为IReadOnlyList返回。

现在来实现IListResult接口,新建ListResult实现类,继承IListResult,在构造函数中为其赋值,代码如下:

//ListResult.cs
using System.Collections.Generic;

namespace Meowv.Blog.ToolKits.Base.Paged
{
public class ListResult : IListResult
{
IReadOnlyList item;

    public IReadOnlyList<T> Item{get => item ?? (item = new List<T>());set => item = value;}public ListResult()

{
}

    public ListResult(IReadOnlyList<T> item)

{
Item = item;
}
}
}
最后新建我们的分页响应实体接口:IPagedList和分页响应实体实现类:PagedList,它同时也要接受一个泛型参数 T。

接口继承了IListResult和IHasTotalCount,实现类继承ListResult和IPagedList,在构造函数中为其赋值。代码如下:

//IPagedList.cs
namespace Meowv.Blog.ToolKits.Base.Paged
{
public interface IPagedList : IListResult, IHasTotalCount
{
}
}

//PagedList.cs
using Meowv.Blog.ToolKits.Base.Paged;
using System.Collections.Generic;

namespace Meowv.Blog.ToolKits.Base
{
///
/// 分页响应实体
///
///
public class PagedList : ListResult, IPagedList
{
///
/// 总数
///
public int Total { get; set; }

    public PagedList(){}public PagedList(int total, IReadOnlyList<T> result) : base(result){Total = total;}
}

}
到这里我们的返回模型就圆满了,看一下此时下我们的项目层级目录。

图片

接下来去实践一下,修改我们之前创建的增删改查接口的返回参数。

//IBlogService.cs
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System.Threading.Tasks;

namespace Meowv.Blog.Application.Blog
{
public interface IBlogService
{
//Task InsertPostAsync(PostDto dto);
Task<ServiceResult> InsertPostAsync(PostDto dto);

    //Task<bool> DeletePostAsync(int id);Task<ServiceResult> DeletePostAsync(int id);//Task<bool> UpdatePostAsync(int id, PostDto dto);Task<ServiceResult<string>> UpdatePostAsync(int id, PostDto dto);//Task<PostDto> GetPostAsync(int id);Task<ServiceResult<PostDto>> GetPostAsync(int id);
}

}

接口全部为异步方式,用ServiceResult包裹作为返回模型,添加和更新T参数为string类型,删除就直接不返回结果,然后查询为:ServiceResult,再看一下实现类:

//BlogService.cs

public async Task<ServiceResult> InsertPostAsync(PostDto dto)
{
var result = new ServiceResult();

        var entity = new Post{Title = dto.Title,Author = dto.Author,Url = dto.Url,Html = dto.Html,Markdown = dto.Markdown,CategoryId = dto.CategoryId,CreationTime = dto.CreationTime};var post = await _postRepository.InsertAsync(entity);if (post == null){result.IsFailed("添加失败");return result;}result.IsSuccess("添加成功");return result;}public async Task<ServiceResult> DeletePostAsync(int id){var result = new ServiceResult();await _postRepository.DeleteAsync(id);return result;}public async Task<ServiceResult<string>> UpdatePostAsync(int id, PostDto dto){var result = new ServiceResult<string>();var post = await _postRepository.GetAsync(id);if (post == null){result.IsFailed("文章不存在");return result;}post.Title = dto.Title;post.Author = dto.Author;post.Url = dto.Url;post.Html = dto.Html;post.Markdown = dto.Markdown;post.CategoryId = dto.CategoryId;post.CreationTime = dto.CreationTime;await _postRepository.UpdateAsync(post);result.IsSuccess("更新成功");return result;}public async Task<ServiceResult<PostDto>> GetPostAsync(int id){var result = new ServiceResult<PostDto>();var post = await _postRepository.GetAsync(id);if (post == null){result.IsFailed("文章不存在");return result;}var dto = new PostDto{Title = post.Title,Author = post.Author,Url = post.Url,Html = post.Html,Markdown = post.Markdown,CategoryId = post.CategoryId,CreationTime = post.CreationTime};result.IsSuccess(dto);return result;}

当成功时,调用IsSuccess(…)方法,当失败时,调用IsFailed(…)方法。最终我们返回的是new ServiceResult()或者new ServiceResult()对象。

同时不要忘记在Controller中也需要修改一下,如下:

//BlogController.cs


public async Task<ServiceResult> InsertPostAsync([FromBody] PostDto dto)

    ...public async Task<ServiceResult> DeletePostAsync([Required] int id)......public async Task<ServiceResult<string>> UpdatePostAsync([Required] int id, [FromBody] PostDto dto)......public async Task<ServiceResult<PostDto>> GetPostAsync([Required] int id)...

此时再去我们的Swagger文档发起请求,这里我们调用一下查询接口看看返回的样子,看看效果吧。

图片

本篇内容比较简单,主要是包装我们的api,让返回结果显得比较正式一点。那么,你学会了吗?

基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型相关推荐

  1. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(一)

    系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...

  2. 基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目

    基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目 转载于:https://github.com/Meowv/Blog 既然开发完成了,还是拿出来溜溜比较好,本篇是本 ...

  3. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(九)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(九) 转载于:https://github.com/Meowv/Blog 终于要接近尾声了,上一篇基本上将文 ...

  4. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(八)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(八) 转载于:https://github.com/Meowv/Blog 上一篇完成了标签模块和友情链接模块 ...

  5. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(七)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(七) 转载于:https://github.com/Meowv/Blog 上一篇完成了后台分类模块的所有功能 ...

  6. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客文章详情页面的数据 ...

  7. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五) 转载于:https://github.com/Meowv/Blog 上一篇完成了分类标签友链的列表查询 ...

  8. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客的分页查询文章列表 ...

  9. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三)

    基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客的主题切换,菜单和 ...

最新文章

  1. 重装云服务器上的系统后的重新部署项目
  2. 机器学习中的逻辑回归
  3. Kernel那些事儿之内存管理(2) --- 百闻不如一见
  4. esplise自定义快捷代码补全_【Eclipse】_Eclipse自动补全增强方法 常用快捷键
  5. poj 1723 中位数
  6. 论坛中的验证码的作用
  7. 【云计算】Kubernetes、Marathon等框架需要解决什么样的问题?
  8. Spring Data + Thymeleaf 3 + Bootstrap 4 实现分页器
  9. 黑塞矩阵(海森矩阵,Hessian Matrix)与牛顿法最优化
  10. python在经济学的应用_『经济学在读研究生学习python可以用来做什么』python经济应用教程...
  11. 计算机房等电位接地规范,一个实例全面讲解机房如何做防雷接地?
  12. linux怎么创建swap分区,linux下创建swap分区
  13. UNI-APP APP版本更新方法
  14. 超像素经典算法SLIC的代码的深度优化
  15. sas简单描述统计分析和散点图
  16. C++语言递归实现求从n个数中选k个进行组合的组合数
  17. C#,图像二值化(20)——全局阈值的耶恩算法(Yen Thresholding)及源代码
  18. F2FS数据块寻址(linux5.18.11)
  19. VC驿站《VC++网络编程班》开课啦!
  20. python第四章上机练习 简单代码

热门文章

  1. 深度探讨 CrossFormer 如何解决跨尺度问题
  2. 基于Elasticsearch的数据报表方案
  3. 0227互联网新闻 | 腾讯与英特尔联合推出云游戏平台“腾讯即玩”;华为企业业务MWC现场发布数字平台...
  4. 《Cloudera hadoop大数据平台实战指南》此书2019年1月已上市
  5. Java easycms 版本2.0发布
  6. db2 之 入门实验
  7. ubuntu 14.04使用devstack安装openstack mitaka版本
  8. java获得服务器路径的几中方法
  9. kafka java客户端编程
  10. Zabbix 监控TCP的SYN,establised