基于 abp vNext 和 .NET Core 开发博客项目 - 统一规范API,包装返回模型
基于 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,包装返回模型相关推荐
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(一)
系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目
基于 abp vNext 和 .NET Core 开发博客项目 - 终结篇之发布项目 转载于:https://github.com/Meowv/Blog 既然开发完成了,还是拿出来溜溜比较好,本篇是本 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(九)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(九) 转载于:https://github.com/Meowv/Blog 终于要接近尾声了,上一篇基本上将文 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(八)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(八) 转载于:https://github.com/Meowv/Blog 上一篇完成了标签模块和友情链接模块 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(七)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(七) 转载于:https://github.com/Meowv/Blog 上一篇完成了后台分类模块的所有功能 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(六) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客文章详情页面的数据 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(五) 转载于:https://github.com/Meowv/Blog 上一篇完成了分类标签友链的列表查询 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客的分页查询文章列表 ...
- 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三)
基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(三) 转载于:https://github.com/Meowv/Blog 上一篇完成了博客的主题切换,菜单和 ...
最新文章
- 重装云服务器上的系统后的重新部署项目
- 机器学习中的逻辑回归
- Kernel那些事儿之内存管理(2) --- 百闻不如一见
- esplise自定义快捷代码补全_【Eclipse】_Eclipse自动补全增强方法 常用快捷键
- poj 1723 中位数
- 论坛中的验证码的作用
- 【云计算】Kubernetes、Marathon等框架需要解决什么样的问题?
- Spring Data + Thymeleaf 3 + Bootstrap 4 实现分页器
- 黑塞矩阵(海森矩阵,Hessian Matrix)与牛顿法最优化
- python在经济学的应用_『经济学在读研究生学习python可以用来做什么』python经济应用教程...
- 计算机房等电位接地规范,一个实例全面讲解机房如何做防雷接地?
- linux怎么创建swap分区,linux下创建swap分区
- UNI-APP APP版本更新方法
- 超像素经典算法SLIC的代码的深度优化
- sas简单描述统计分析和散点图
- C++语言递归实现求从n个数中选k个进行组合的组合数
- C#,图像二值化(20)——全局阈值的耶恩算法(Yen Thresholding)及源代码
- F2FS数据块寻址(linux5.18.11)
- VC驿站《VC++网络编程班》开课啦!
- python第四章上机练习 简单代码
热门文章
- 深度探讨 CrossFormer 如何解决跨尺度问题
- 基于Elasticsearch的数据报表方案
- 0227互联网新闻 | 腾讯与英特尔联合推出云游戏平台“腾讯即玩”;华为企业业务MWC现场发布数字平台...
- 《Cloudera hadoop大数据平台实战指南》此书2019年1月已上市
- Java easycms 版本2.0发布
- db2 之 入门实验
- ubuntu 14.04使用devstack安装openstack mitaka版本
- java获得服务器路径的几中方法
- kafka java客户端编程
- Zabbix 监控TCP的SYN,establised