从零写一个Asp.net core手脚架(模型验证)
一个asp.net core项目,一定包含了各种的实体,在RESTful api里面,有很多的参数传递,不建立实体则大量的参数需要自定验证正确性,并且Action上面会写的密密麻麻的参数
在asp.net 2.0的时候,就推出了ModelState,顾名思义,这个是模型状态,用于验证实体对象的
如何模型验证
用法是在需要验证的地方打上继承了ValidationAttribute的特性,比如常见的RequiredAttribute,这个是验证对象是否存在
/// <summary>
/// Admin Request Model
/// </summary>
public class AdminRequestModel
{
/// <summary>
/// User
/// </summary>
[Required]
public string User { get; set; } /// <summary>
/// Account
/// </summary>
[Required]
public string Account { get; set; }
}
这是一个实体
我们要验证的Model里是“User”属性和“Account”属性不能为空
写在Action上面
/// <summary>
/// Test Admin
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost("Admin")]
public ResponseModel Admin(AdminRequestModel model)
{
return new AdminResponseModel()
{
User = model.User
};
}
在asp.net core 2.1之前版本的web api则改为
/// <summary>
/// Test Admin
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost("Admin")]
public ResponseModel Admin([FromForm] AdminRequestModel model)
{
return new AdminResponseModel()
{
User = model.User
};
}
进入了Action的就是通过了基础模型验证的实体对象,数据库操作之类的业务验证,就在Action里面处理
怎么启用模型验证
全局过滤器
/// <summary>
/// Gold Filter Validate Model
/// </summary>
public class GoldModelFilter : IActionFilter
{
/// <summary>
/// Action Before
/// </summary>
/// <param name="context"></param>
public void OnActionExecuted(ActionExecutedContext context)
{
} /// <summary>
/// Action After
/// </summary>
/// <param name="context"></param>
public void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
throw new ValidateException(
context.ModelState.Values
.FirstOrDefault(item => item.Errors.Count >
)
.Errors.FirstOrDefault().ErrorMessage
);
}
}
然后在
Startup.cs的ConfigureService内写的AddMvc改为
services.AddMvc(options=> {
options.Filters.Add<GoldModelFilter>();
}));
我们不需要全局验证的则这样写
public class ModelFilterAttribute:ActionFilterAttribute
{
/// <summary>
/// Action Before
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuted(ActionExecutedContext context)
{
//leave out
} /// <summary>
/// Action After
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuting(ActionExecutingContext context)
{
//leave out
}
}
是不是很像,是的,就是一样的,只是一个是特性,一个是过滤器,内部的流程也差不多
ActionFilterAttribute还有很多东西,就暂不赘述了
我们在需要模型验证的Action上面打上特性就可以了
如何扩展自定义模型验证
CustomValidationAttribute,顾名思义这个是做自定义模型验证的,支持给属性、字段、方法、参数和实体对象验证的
他有两个参数,参数1是自定义的验证类Type,参数2是方法名
自定义验证类需要是公开类,自定义方法也是公开方法
方法参数1是object类型,参数2是ValidationContext类型
参数1是验证的内容,参数2是验证的上下文
包括
DisplayName 描述名
MemberName 成员名
ObjectInstance 整个验证的实体
ObjectType 整个验证的实体类型
还一个方法GetService
这个是获取服务的,依赖注入里面的服务,可以通过这个取出来
如果我们要对之前的AdminRequestModel这个实体验证User是否等于Account,不等于,则写一条错误日志,然后验证失败
/// <summary>
/// Admin Validate
/// </summary>
public class AdminValidate
{
/// <summary>
/// Ordinary Validate
/// </summary>
/// <param name="value"></param>
/// <param name="validationContext"></param>
/// <returns></returns>
public static ValidationResult Ordinary(object value, ValidationContext validationContext)
{
if (value is AdminRequestModel model)
{
if (!model.User.Equals(model.Account))
{
var logger = validationContext.GetService(typeof(ILogger<AdminValidate>)) as ILogger<AdminValidate>; logger.LogError("User not equals Account"); return new ValidationResult("User not equals Account");
} return ValidationResult.Success;
} return new ValidationResult("Type Error");
}
}
AdminRequestModel上面加一行[CustomValidation(typeof(AdminValidate), "Ordinary")]
这种是低复用的场景下,给特定的做验证的,如果我们这种验证很多,而且很多处都有相似的验证,那么可以写一个特性,继承ValidationAttribute
这个的验证的有两种场景,单纯的内容验证,没有功能性的,比如上面这种,验证失败,悄悄写一条错误日志,甚至发一个预警邮件
那么重构两个方法FormatErrorMessage和IsValid,前者返回错误信息,后者是验证的
除了验证,还有一些功能性的
那么请重构IsValid方法
代码和AdminValidate.Ordinary雷同
扩展
如果我们的过滤特性里面也有一些功能性呢?
/// <summary>
/// Register Service Action Filter
/// </summary>
public class ServiceActionFilterAttribute : ActionFilterAttribute
{
private ILogger<ServiceActionFilterAttribute> Logger { get; } /// <summary>
/// Generate
/// </summary>
/// <param name="logger"></param>
public ServiceActionFilterAttribute(ILogger<ServiceActionFilterAttribute> logger)
{
Logger = logger;
} /// <summary>
/// Action Before
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuted(ActionExecutedContext context)
{
//leave out
} /// <summary>
/// Action After
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuting(ActionExecutingContext context)
{
//leave out
}
}
这样是不能打在Action上面了
这个时候,我们就要掏出ServiceFilterArribute或者TypeFilterAttribute
/// <summary>
/// Test Admin
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost("AdminDIFilterAttibute")]
[ServiceFilter(typeof(ServiceActionFilterAttribute))]
public ResponseModel AdminDIFilterAttibute(AdminRequestModel model)
{
return new AdminResponseModel()
{
User = model.User
};
}
前者是Type必须注册在依赖注入容器里面的,后者是不需要的
项目地址:
https://github.com/htrlq/AspNetCoreTemplate
从零写一个Asp.net core手脚架(模型验证)的更多相关文章
- 从零写一个Asp.net core手脚架 (异常处理)
既然是手脚架,那么肯定得明白,手脚架是有限资源的一个整合,我们尽可能完善它,并保留可扩展性才是最终目的,尽可能减少硬编码,让业务不满足的情况下,可以自行修改 我们把解决方案取名Asp.netCoreT ...
- asp.net core 简化模型验证 modelState.IsValid不用每一个写
第一种:直接在执行action之前验证模型 实现 IActionFilter public class ModelStateFilter : IActionFilter { public void O ...
- asp.net core自定义模型验证——前端验证
转载请注明出处:http://www.cnblogs.com/zhiyong-ITNote/ 官方网站:https://docs.microsoft.com/zh-cn/aspnet/core/mvc ...
- Asp.Net Core 全局模型验证
public class ActionFilter : IActionFilter { /// <summary> /// action 执行之前 /// </summary> ...
- 手把手教你从零写一个简单的 VUE--模板篇
教程目录1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 Hello,我又回来了,上一次的文章教会了大家如何书写一个简单 VUE,里面实现了VUE 的数据驱动视图 ...
- Kubernetes初探[1]:部署你的第一个ASP.NET Core应用到k8s集群
Kubernetes简介 Kubernetes是Google基于Borg开源的容器编排调度引擎,作为CNCF(Cloud Native Computing Foundation)最重要的组件之一,它的 ...
- 使用Visual Studio Code创建第一个ASP.NET Core应用程序
全文翻译自:Your First ASP.NET Core Application on a Mac Using Visual Studio Code 这篇文章将向你展示如何在Mac上写出你的第一个A ...
- 如何一秒钟从头构建一个 ASP.NET Core 中间件
前言 其实地上本没有路,走的人多了,也便成了路. -- 鲁迅 就像上面鲁迅说的那样,其实在我们开发中间件的过程中,微软并没有制定一些策略或者文档来约束你如何编写一个中间件程序, 但是其中却存在者一些最 ...
- 手把手教你从零写一个简单的 VUE
本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...
随机推荐
- python入门008
目录 一.for循环 作用:for循环是因为在循环取值(即遍历值)时for循环比while循环的使用更为简洁 1.for循环语法: 2.应用案例: 注意:break 与 continue也可以用于fo ...
- 从0开始,手把手教你用Vue开发一个答题App
项目演示 项目演示 项目源码 项目源码 教程说明 本教程适合对Vue基础知识有一点了解,但不懂得综合运用,还未曾使用Vue从头开发过一个小型App的读者.本教程不对所有的Vue知识点进行讲解,而是手把 ...
- [HCTF 2018]admin
前言: 最近在BUUCTF刷题,参照师傅们wp后复现一下 0x01 拿到题目后进去如下界面 发现有登录和注册界面,相比是要登录后才能查看想要的信息. 查看页面源代码,看看有没有上面提示,界面如下 提示 ...
- 数据库02 /MySQL基础数据类型、完整性约束、sql_mode模式
2.MySQL基础数据类型.完整性约束.sql_mode模式 目录 2.MySQL基础数据类型.完整性约束.sql_mode模式 1. MySQL常用数据类型 MySQL常用数据类型预览 1. 1 数 ...
- 前端04 /css样式
前端04 /css样式 目录 前端04 /css样式 昨日内容回顾 css引入 选择器 基础选择器 组合选择器 属性选择器 伪类选择器 伪元素选择器 优先级(权重) 通用选择器 css样式 1高度宽度 ...
- Python函数04/生成器/推导式/内置函数
Python函数04/生成器/推导式/内置函数 目录 Python函数04/生成器/推导式/内置函数 内容大纲 1.生成器 2.推导式 3.内置函数(一) 4.今日总结 5.今日练习 内容大纲 1.生 ...
- Python实现性能自动化测试竟然如此简单【颠覆你的三观】
一.思考 1.什么是性能自动化测试? 性能系统负载能力 超负荷运行下的稳定性 系统瓶颈 自动化测试使用程序代替手工 提升测试效率 性能自动化使用代码模拟大批量用户 让用户并发请求 多页面多用户并发 ...
- Spring-Boot 多数据源配置+动态数据源切换+多数据源事物配置实现主从数据库存储分离
一.基础介绍 多数据源字面意思,比如说二个数据库,甚至不同类型的数据库.在用SpringBoot开发项目时,随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源. ...
- 详解 CmProcess 跨进程通信的实现
CmProcess 是 Android 一个跨进程通信框架,整体代码比较简单,总共 20 多个类,能够很好的便于我们去了解跨进程实现的原理. 个人猜测 CmProcess 也是借鉴了 VirtualA ...
- 设计模式:decorator模式
两点: 继承同一虚接口,实现数据一致性 桥接方式指向被装饰类 目的:在不改变被装饰类功能的前提下增加新功能 特点:继承是子类和父类强耦合,桥接是低耦合 例子: class Print //抽象接口 { ...