zoukankan      html  css  js  c++  java
  • ASP.NET Core搭建多层网站架构【8.1-使用ViewModel注解验证】

    2020/01/29, ASP.NET Core 3.1, VS2019

    摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构【8.1-使用ViewModel注解验证】
    使用ViewModel注解验证字段合法性,将ViewModel的字段验证写在了ViewModel类内部

    文章目录

    此分支项目代码

    本章节介绍了使用ASP.NET Core自带的注解验证前端提交的参数

    确认MS.Models类库已引用MS.Component.JwtMS.DbContexts两个项目

    添加业务操作枚举和返回值定义

    MS.WebCore类库中新建Core文件夹,在该文件夹中新建ExecuteResult.csExecuteType.cs类:

    ExecuteResult.cs

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

    这个类是定义了业务相关方法调用的返回值结果,包含了是否成功、错误信息,也可以拓展泛型夹带其他内容

    ExecuteType.cs

    namespace MS.WebCore.Core
    {
        /// <summary>
        /// 表示操作数据库类型
        /// </summary>
        public enum ExecuteType
        {
            /// <summary>
            /// 读取资源
            /// </summary>
            Retrieve,
            /// <summary>
            /// 创建资源
            /// </summary>
            Create,
            /// <summary>
            /// 更新资源
            /// </summary>
            Update,
            /// <summary>
            /// 删除资源
            /// </summary>
            Delete
        }
    }
    

    这个枚举定义了业务操作的类型,对应数据库的CRUD

    新建ViewModel

    MS.Models类库中新建ViewModel文件夹,在该文件夹中新建RoleViewModel.cs类:

    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;//没有错误,默认返回成功
            }
        }
    }
    
    

    说明

    • Display是该字段的显示名称
    • Required注解标记该字段必填,不可为空
    • StringLength注解标记该字段长度
    • RegularExpression注解是正则表达式验证
    • 还有个Range注解特性是验证值的范围的,这里没用到

    除了注解,我把对象字段的逻辑验证写在了ViewModel中,没有把它放在业务层是因为,我认为对象字段本身的合法性和对象是强相关的,就和注解直接写在ViewModel中而不是Service中一样,所以把字段的验证也写在了ViewModel里

    对象字段的逻辑验证我区分了操作类型,新增时检查角色名是否有重复;删除时检查是否还有用户使用该角色;更新时检查用户提交的角色是否存在于数据库中

    新建Controller

    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.csWeatherForecast.cs两个类

    完成后,启动项目,打开Postman
    按之前的方法,在MSDemo集合中添加一个新的POST请求Role,URL为http://localhost:5000/role
    切换到Body选项卡,选择raw,切换为json格式数据:

    {
        "Name": "",
        "DisplayName": ""
    }
    

    点击发送,可以看到提示字段必填了

    输入正确后,能返回true

    Name输入超过16个字符错误,验证正则表达式等不再演示

    以上便是ViewModel注解验证的使用

    项目完成后,如下图所示

  • 相关阅读:
    【程序2】
    【程序1】
    基数排序
    归并排序
    选择排序
    leetcode15
    leetcode221
    leetcode322
    leetcode921
    leetcode922
  • 原文地址:https://www.cnblogs.com/kasnti/p/12240330.html
Copyright © 2011-2022 走看看