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注解验证的使用

项目完成后,如下图所示

ASP.NET Core搭建多层网站架构【8.1-使用ViewModel注解验证】的更多相关文章

  1. ASP.NET Core搭建多层网站架构【0-前言】

    2020/01/26, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构 目录 0-前言 1-项目结构分层建立 2-公共基 ...

  2. ASP.NET Core搭建多层网站架构【1-项目结构分层建立】

    2020/01/26, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[1-项目结构分层建立] 文章目录 此分支项目代码 ...

  3. ASP.NET Core搭建多层网站架构【2-公共基础库】

    2020/01/28, ASP.NET Core 3.1, VS2019,Newtonsoft.Json 12.0.3, Microsoft.AspNetCore.Cryptography.KeyDe ...

  4. ASP.NET Core搭建多层网站架构【3-xUnit单元测试之简单方法测试】

    2020/01/28, ASP.NET Core 3.1, VS2019, xUnit 2.4.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[3-xUnit单元测试 ...

  5. ASP.NET Core搭建多层网站架构【4-工作单元和仓储设计】

    2020/01/28, ASP.NET Core 3.1, VS2019, Microsoft.EntityFrameworkCore.Relational 3.1.1 摘要:基于ASP.NET Co ...

  6. ASP.NET Core搭建多层网站架构【5-网站数据库实体设计及映射配置】

    2020/01/29, ASP.NET Core 3.1, VS2019, EntityFrameworkCore 3.1.1, Microsoft.Extensions.Logging.Consol ...

  7. ASP.NET Core搭建多层网站架构【6-注册跨域、网站核心配置】

    2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...

  8. ASP.NET Core搭建多层网站架构【7-使用NLog日志记录器】

    2020/01/29, ASP.NET Core 3.1, VS2019, NLog.Web.AspNetCore 4.9.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站 ...

  9. ASP.NET Core搭建多层网站架构【8.2-使用AutoMapper映射实体对象】

    2020/01/29, ASP.NET Core 3.1, VS2019, AutoMapper.Extensions.Microsoft.DependencyInjection 7.0.0 摘要:基 ...

随机推荐

  1. 53最大子序和.py

    题目:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 来源:https://leetcode-cn.com/problems/maximum-s ...

  2. JQ 获取浏览器窗口宽高

    $(window).height(); // 浏览器时下窗口可视区域高度 $(document).height(); //浏览器时下窗口文档的高度 $(document.body).height(); ...

  3. mybatis-plus 错误

    错误:java.lang.NoClassDefFoundError: org/apache/velocity/context/Context 原因: 缺少velocity的依赖 解决方案: <d ...

  4. PLL

    PLL(Phase Locked Loop): 为锁相回路或锁相环,用来统一整合时脉讯号,使内存能正确的存取资料.PLL用于振荡器中的反馈技术. 许多电子设备要正常工作,通常需要外部的输入信号与内部的 ...

  5. FLAG-回归C++,JAVA什么的等学校教吧

    以后刷OJ还是写C++,昂啊! 除非我觉得JAVA更好用

  6. 【译】使用 Rust 和 WebAssembly 构建离线画图页面

    原文地址:https://dev.to/sendilkumarn/create-dev-s-offline-page-with-rust-and-webassembly-21gn 原文仓库:https ...

  7. L2-1 分而治之

    思路 这题的意思是,如果把这些点打掉,其他的点是否能够完全不连通. 用并查集,或者打上标记之后,判断每个点是否还能到达其他点,如果一个点可以到达其他任何点,都应该输出否. 代码 #include &l ...

  8. kmp算法基础

    https://www.luogu.com.cn/problemnew/solution/P3375 #include<bits/stdc++.h> using namespace std ...

  9. Spark学习笔记1

    趁着工作业余时间,趁着内心对技术追求的热情,还是对Spark这个大数据内存计算框架动手了,毕竟人与人之间的差距都是在工作业余时间拉开的…… Spark官网:http://spark.apache.or ...

  10. 【转载】Win7下如何使用GCC编译器

    转自:http://jingyan.baidu.com/article/c275f6bacc0126e33c756771.html 双击GCC安装包,mingw-get-setup.exe,点击Ins ...