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. 【牛客小白月赛21】NC201604 Audio

    [牛客小白月赛21]NC201604 Audio 题目链接 题目大意: 给出三点 ,求到三点距离相等的点 的坐标. 解析 考点:计算几何基础. 初中蒟蒻表示不会什么法向量.高斯消元..qwq 方法一: ...

  2. c++primer练习题

    2.7 输出地址和姓名(1 #include <iostream> using namespace std; int main() { int 距离; cout << &quo ...

  3. jenkins常用

    记最精简版的启动:gradle集成springboot+vue 安装jenkins,安装待推荐插件 服务器安装gradle 服务器安装npm 配置git仓库,配置git开发者账号等 配置gradle构 ...

  4. 怎么把VS里的scanf_s换成scanf

    转自:https://blog.csdn.net/hansionz/article/details/79889039 方法一:在项目属性中---->配置属性------>C\C++---- ...

  5. 发送数据给sap和接收

    1.确保已经连通sap 2.发送数据:这是以表的形式发送,而且是批量发送给sap 3.接收sap返回信息:这个比较特别,碰到时试一试 package com.yiyezhiqiu.lyh.utils; ...

  6. mysql基本约定与命名规范

    一.约定 1.如无特殊需求,所有表使用innodb引擎 2.如无特殊需求,所有主键均为自增类型 3.如无特殊需求,所有字段均为NOT NULL,并给定默认值 4.所有字段均设置备注,枚举字段需要说明每 ...

  7. MyBatis(6)——分页的实现

    分页的实现 a)通过mysql的分页查询语句: 说明:sql的分页语句格式为select * from aaa limit #{startIndex},#{pageSize} //---------- ...

  8. 关于Excel,你一定用的到的36个Python函数

    从Excel到Python:最常用的36个Pandas函数关于Excel,你一定用的到的36个Python函数 本文涉及pandas最常用的36个函数,通过这些函数介绍如何完成数据生成和导入.数据清洗 ...

  9. Django流程-以登录功能为例

    Django流程-以登录功能为例 一.注意点 1.新创建的app一定要先去settings.py注册 简写:'app01' 完整:'app01.apps.App01Config' 2.启动Django ...

  10. gulp 常用方法 任务 插件

    执行gulp 任务 gulp taskname (default任务不输入名称亦可:gulp) var gulp = require("gulp"); gulp.task(&quo ...