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註解驗證的使用
項目完成後,以下圖所示