2020/01/29, ASP.NET Core 3.1, VS2019html
摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构【8.1-使用ViewModel注解验证】
使用ViewModel注解验证字段合法性,将ViewModel的字段验证写在了ViewModel类内部前端
文章目录git
此分支项目代码github
本章节介绍了使用ASP.NET Core自带的注解验证前端提交的参数正则表达式
确认MS.Models
类库已引用MS.Component.Jwt
、MS.DbContexts
两个项目数据库
在MS.WebCore
类库中新建Core文件夹,在该文件夹中新建ExecuteResult.cs
、ExecuteType.cs
类:json
namespace MS.WebCore.Core { /// <summary> /// 执行返回结果 /// </summary> public class ExecuteResult { public virtual ExecuteResult Set(bool isSucceed, string message) { IsSucceed = isSucceed; Message = message; return this; } /// <summary> /// 设定错误信息 /// </summary> /// <param name="message"></param> /// <returns></returns> public virtual ExecuteResult SetFailMessage(string message) { return Set(false, message); } public virtual ExecuteResult SetFail() { return Set(false, string.Empty); } public ExecuteResult(bool isSucceed, string message) { Set(isSucceed, message); } /// <summary> /// 若是是给字符串,表示有错误信息,默认IsSucceed=false /// </summary> /// <param name="message"></param> public ExecuteResult(string message) { Set(false, message); } /// <summary> /// 若是是空的,没有信息,默认IsSucceed=true /// </summary> public ExecuteResult() { } /// <summary> /// 执行是否成功 /// 默认为True /// </summary> public bool IsSucceed { get; set; } = true; /// <summary> /// 执行信息(通常是错误信息) /// 默认置空 /// </summary> public string Message { get; set; } = string.Empty; } /// <summary> /// 执行返回结果 /// </summary> /// <typeparam name="T"></typeparam> public class ExecuteResult<T> : ExecuteResult { public ExecuteResult<T> Set(bool isSucceed, string message, T result) { IsSucceed = isSucceed; Message = message; Result = result; return this; } public ExecuteResult<T> SetData(T data) { return Set(true, string.Empty, data); } public new ExecuteResult<T> SetFail() { return Set(false, string.Empty, default); } /// <summary> /// 设定错误信息 /// 若是T正好也是string类型,可能set方法会存在用错的时候,因此取名SetMessage更明确 /// </summary> /// <param name="message"></param> /// <returns></returns> public new ExecuteResult<T> SetFailMessage(string message) { return Set(false, message, default); } public ExecuteResult() { } public ExecuteResult(string message) { Set(false, message); } public ExecuteResult(bool isSucceed, string message) { Set(isSucceed, message); } public ExecuteResult(T result) { SetData(result); } public T Result { get; set; } } }
这个类是定义了业务相关方法调用的返回值结果,包含了是否成功、错误信息,也能够拓展泛型夹带其余内容后端
namespace MS.WebCore.Core { /// <summary> /// 表示操做数据库类型 /// </summary> public enum ExecuteType { /// <summary> /// 读取资源 /// </summary> Retrieve, /// <summary> /// 建立资源 /// </summary> Create, /// <summary> /// 更新资源 /// </summary> Update, /// <summary> /// 删除资源 /// </summary> Delete } }
这个枚举定义了业务操做的类型,对应数据库的CRUD架构
在MS.Models
类库中新建ViewModel文件夹,在该文件夹中新建RoleViewModel.cs
类:async
using MS.DbContexts; using MS.Entities; using MS.UnitOfWork; using MS.WebCore.Core; using System.ComponentModel.DataAnnotations; namespace MS.Models.ViewModel { public class RoleViewModel { public long Id { get; set; } [Display(Name = "角色名称")] [Required(ErrorMessage = "{0}必填")] [StringLength(16, ErrorMessage = "不能超过{0}个字符")] [RegularExpression(@"^[a-zA-Z0-9_]{4,16}$", ErrorMessage = "只能包含字符、数字和下划线")] public string Name { get; set; } [Display(Name = "角色显示名")] [Required(ErrorMessage = "{0}必填")] [StringLength(50, ErrorMessage = "不能超过{0}个字符")] public string DisplayName { get; set; } [Display(Name = "备注")] [StringLength(4000, ErrorMessage = "不能超过{0}个字符")] public string Remark { get; set; } public ExecuteResult CheckField(ExecuteType executeType, IUnitOfWork<MSDbContext> unitOfWork) { ExecuteResult result = new ExecuteResult(); var repo = unitOfWork.GetRepository<Role>(); //若是不是新增角色,操做以前都要先检查角色是否存在 if (executeType != ExecuteType.Create && !repo.Exists(a => a.Id == Id)) { return result.SetFailMessage("角色不存在"); } //针对不一样的操做,检查逻辑不一样 switch (executeType) { case ExecuteType.Delete: //删除角色前检查角色下尚未员工 if (unitOfWork.GetRepository<User>().Exists(a => a.RoleId == Id)) { return result.SetFailMessage("还有员工正在使用该角色,没法删除"); } break; case ExecuteType.Update: //若是存在Id不一样,角色名相同的实体,则返回报错 if (repo.Exists(a => a.Name == Name && a.Id != Id)) { return result.SetFailMessage($"已存在相同的角色名称:{Name}"); } break; case ExecuteType.Create: default: //若是存在相同的角色名,则返回报错 if (repo.Exists(a => a.Name == Name)) { return result.SetFailMessage($"已存在相同的角色名称:{Name}"); } break; } return result;//没有错误,默认返回成功 } } }
除了注解,我把对象字段的逻辑验证写在了ViewModel中,没有把它放在业务层是由于,我认为对象字段自己的合法性和对象是强相关的,就和注解直接写在ViewModel中而不是Service中同样,因此把字段的验证也写在了ViewModel里
对象字段的逻辑验证我区分了操做类型,新增时检查角色名是否有重复;删除时检查是否还有用户使用该角色;更新时检查用户提交的角色是否存在于数据库中
在MS.WebApi
应用程序中,Controllers文件夹下新建RoleController.cs
:
using Microsoft.AspNetCore.Mvc; using MS.Models.ViewModel; using MS.WebCore.Core; using System.Threading.Tasks; namespace MS.WebApi.Controllers { [Route("[controller]")] [ApiController] public class RoleController : ControllerBase { [HttpPost] public async Task<ExecuteResult> Post(RoleViewModel viewModel) { return new ExecuteResult(); } } }
删除WeatherForecastController.cs
和WeatherForecast.cs
两个类
完成后,启动项目,打开Postman
按以前的方法,在MSDemo集合中添加一个新的POST请求Role,URL为http://localhost:5000/role
切换到Body选项卡,选择raw,切换为json格式数据:
{ "Name": "", "DisplayName": "" }
点击发送,能够看到提示字段必填了
输入正确后,能返回true
Name输入超过16个字符错误,验证正则表达式等再也不演示
以上即是ViewModel注解验证的使用
项目完成后,以下图所示