在.NET Core 中使用 FluentValidation 进行规则验证

不用说,规则验证很重要,无效的参数,可能会导致程序的异常。

如果使用Web API或MVC页面,那么可能习惯了自带的规则验证,我们的控制器很干净:

public class User
{[Required]public string FirstName { get; set; }[Required]public string LastName { get; set; }
}

这种很常见,但是今天我想给你一个更好的替代方案:FluentValidation, 通过这个库,您可以流畅地定义用于对象验证的复杂规则,从而轻松构建和理解验证规则,您可以在 Github[1] 上找到这个项目。

安装 FluentValidation

我新建了一个很简单的.NET Core 的Web API 程序,只有一个接口是用户注册,入参是一个User类, 然后在Nuget中安装 FluentValidation

创建第一个验证

对于要验证的每个类,必须创建其自己的验证器,每个验证器类都必须继承AbstractValidator<T>,其中T是要验证的类,并且所有验证规则都在构造函数中定义。

最简单的验证是针对空值,如果要指定FirstName和LastName都不能为空,这个验证器是这样:

public class UserValidator : AbstractValidator<User>
{public UserValidator(){RuleFor(x => x.FirstName).NotEmpty();RuleFor(x => x.LastName).NotEmpty();}
}

就这些了,您已经创建了第一个验证器,是不是超级简单!

还有一些其他的规则,比如 MinimumLength,MaximumLength和Length,用于验证长度,您可以把多个规则指定到一个字段,就像这样:

public class UserValidator : AbstractValidator<User>
{public UserValidator(){RuleFor(x => x.FirstName).NotEmpty();RuleFor(x => x.FirstName).MinimumLength(3);RuleFor(x => x.FirstName).MaximumLength(20);RuleFor(x => x.LastName).NotEmpty();}
}

验证入参

我们之前已经定义了验证规则,现在开始使用它,您只需要new 一个UserValidator对象,然后调用Validate方法, 它会返回一个对象,其中包含了验证状态和所有没有通过验证的信息。

[HttpPost]
public IActionResult Register(User newUser)
{var validator = new UserValidator();var validationResult = validator.Validate(newUser);if (!validationResult.IsValid){return BadRequest(validationResult.Errors.First().ErrorMessage);}return Ok();
}

如果我运行程序,然后输入一个超长的名字:

{"FirstName": "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张","LastName": "张"
}

我会收到验证错误:"The length of 'First Name' must be 20 characters or fewer. You entered 24 characters"。

好吧,我不喜欢这个消息,那么你可以自定义错误消息,这很简单,您可以使用 WithMessage 方法。

- RuleFor(x => x.FirstName).MaximumLength(20);
+ RuleFor(x => x.FirstName).MaximumLength(20).WithMessage("您的名字长度已经超出了限制!");

流利验证

你可以把验证规则,改成下边这样:

- RuleFor(x => x.FirstName).NotEmpty();
- RuleFor(x => x.FirstName).MinimumLength(3);
+ RuleFor(x => x.FirstName).NotEmpty().MinimumLength(3);

然后也可以把验证规则应用于其他的属性,就像这样:

public UserValidator()
{RuleFor(x => x.FirstName).MaximumLength(20).WithMessage("您的名字长度已经超出了限制!").NotEmpty().MinimumLength(3);RuleFor(x => x.LastName).NotEmpty();
}

常见的验证规则

这个库有很多现成的基本类型验证规则, 对于字符串,您可以使用不同的方法,比如 EmailAddress,IsEnumName(检查值是否在指定的Enum类型中定义)和 InclusiveBetween, 检查该值是否在定义的范围内。

现在,我在User类添加了另外两个字段,Password 和 ConfirmPassword。

Password字段是一个字符串,有效的长度必须在5到15个字符之间,并且要符合正则,为了定义是否满足安全规则,我定义了一个HasValidPassword方法,它会返回一个bool值。

private bool HasValidPassword(string pw)
{var lowercase = new Regex("[a-z]+");var uppercase = new Regex("[A-Z]+");var digit = new Regex("(\\d)+");var symbol = new Regex("(\\W)+");return (lowercase.IsMatch(pw) && uppercase.IsMatch(pw) && digit.IsMatch(pw) && symbol.IsMatch(pw));
}

然后在密码验证中使用:

RuleFor(x => x.FirstName).MaximumLength(20).WithMessage("您的名字长度已经超出了限制!").NotEmpty().MinimumLength(3);RuleFor(x => x.LastName).NotEmpty();RuleFor(x => x.Password).Length(5, 15).Must(x => HasValidPassword(x));

还可以简化一些:

RuleFor(x => x.Password).Length(5, 15)
-            .Must(x => HasValidPassword(x));
+            .Must(HasValidPassword);}

ConfirmPassword字段的唯一要求是等于Password字段:

RuleFor(x => x.ConfirmPassword).Equal(x => x.Password).WithMessage("2次密码不一致!");

注入验证器

修改Startup类中的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
{services.AddControllers().AddFluentValidation();services.AddTransient<IValidator<User>, UserValidator>();
}

注意:这个地方的生命周期是 Transient。

这样,在调用注册接口的时候,会自动进行规则验证:

[HttpPost]
public IActionResult Register(User newUser)
{return Ok();
}

然后,我们再尝试传入参数来调用接口:

{"FirstName": "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张","LastName": "张"
}

很明显,验证不通过,接口会返回这样的错误信息:

{"type": "https://tools.ietf.org/html/rfc7231#p-6.5.1","title": "One or more validation errors occurred.","status": 400,"traceId": "|c4523c02-4899b7f3df86a629.","errors": { "FirstName": ["您的名字长度已经超出了限制!"]}
}

希望对您有帮助,您可以在官方文档中找到更多的用法。

原文链接: https://www.code4it.dev/blog/fluentvalidation[2]

最后

欢迎扫码关注我们的公众号 【全球技术精选】,专注国外优秀博客的翻译和开源项目分享,也可以添加QQ群 897216102

References

[1] Github: "https://github.com/FluentValidation/FluentValidation"
[2] https://www.code4it.dev/blog/fluentvalidation: "https://www.code4it.dev/blog/fluentvalidation"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/304642.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

scrcpy投屏_安卓投屏利器——PC一键控制多台手机

点击关注&#xff0c;我们共同每天进步一点点&#xff01;之前给大家介绍了投屏开源工具scrcpy(Scrcpy投屏&#xff0c;在电脑上流畅操控你的手机&#xff01;)&#xff0c;今天要介绍的投屏工具是在scrcpy的基础上进行了二次开发&#xff0c;使用更加友好。《安卓投屏》基于Gi…

java emoji编码转换_java转换emoji表情

/*** Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式(表情占4个字节&#xff0c;需要utf8mb4字符集)* param str* 待转换字符串* return 转换后字符串* throws UnsupportedEncodingException* exception*/public static String emojiConvert1(St…

【干货】通俗理解神经网络中激活函数作用

推荐阅读时间8min~13min主要内容&#xff1a;通俗理解激活函数&#xff0c;主要来自我在学习会的slides&#xff0c;讲解了激活函数的非线性能力和组合特征的作用下面我分别对激活函数的两个作用进行解释。1加入非线性因素&#xff0c;解决非线性问题好吧&#xff0c;很容易能够…

创建第一个WCF程序

WCF的三大核心是ABC A代表Address-where&#xff08;对象在哪里&#xff09; B代表Binding-how&#xff08;通过什么协议取得对象&#xff09; C代表Contact&#xff08;契约&#xff09;-what&#xff08;定义的对象是什么&#xff0c;如何操纵&#xff09; 创建一个空的解决方…

.NET微服务最佳实践eShopOnContainers

本文翻译自微软Docs&#xff0c; 内嵌译者多年使用的参悟&#xff0c;如理解有误&#xff0c;请不吝赐教。微软与社区专家合作&#xff0c;开发了功能齐全的云原生微服务示例应用eShopOnContainers。该应用旨在展示使用.NET、Docker以及可选的Azure&#xff0c;Kubernetes技术来…

爬取猎聘python_爬取猎聘大数据岗位相关信息--Python

猎聘网站搜索大数据关键字&#xff0c;只能显示100页&#xff0c;爬取这一百页的相关信息&#xff0c;以便做分析。__author__ ‘Fred Zhao‘import requestsfrom bs4 import BeautifulSoupimport osimport csvclass JobSearch():def __init__(self):self.headers {‘User-Ag…

java string底层实现_Java-学习日记(Shell与String底层原理)

Java杂记-2020.08.07Test中测试所有getter,setter方法最近一周在写codereview&#xff0c;相关技术是kmock1.0.19&#xff0c;gradlebuild.gradle中配置文件testCompile pl.pojo:pojo-tester:0.7.6testCompile(junit:junit:4.12)testCompile(kmock:kmock:1.0.19)Test中的使用&a…

正态分布为什么常见?

统计学里面&#xff0c;正态分布&#xff08;normal distribution&#xff09;最常见。男女身高、寿命、血压、考试成绩、测量误差等等&#xff0c;都属于正态分布。>>>> 作者&#xff1a; 阮一峰以前&#xff0c;我认为中间状态是事物的常态&#xff0c;过高和过低…

Hibernate HQL 语法大全(上)

Hibernate配备了一种非常强大的查询语言&#xff0c;这种语言看上去很像SQL。但是不要被语法结构上的相似所迷惑&#xff0c;HQL是非常有意识的被设计为完全面向对象的查询&#xff0c;它可以理解如继承、多态 和关联之类的概念。 1.大小写敏感性问题 除了Java类与属性的名称外…

python tuple args_Python基本数据类型之tuple

一、创建元组&#xff1a;ages (11, 22, 33, 44, 55)ages tuple((11, 22, 33, 44, 55))元组和列表几乎一样元组的元素不可修改&#xff0c;但是元组元素的元素是可以修改的tuple(iterable)&#xff0c;可以存放所有可迭代的数据类型二、基本操作&#xff1a;索引name_tuple …

轻量级Excel读取器ExcelReader

用户上传Excel文件&#xff0c;要求读取里面数据&#xff0c;其实可以很简单&#xff01;新版Excel2007以上的xlsx文件&#xff0c;本质上是OpenXml格式&#xff0c;只需要解开压缩包然后读取内部Xml即可得到想要的数据。ExcelReader 用于快速读取单Sheet的Excel数据&#xff0…

java代码实现链表_java单链表代码实现

用惯了C&#xff0c;java写起来果然不太爽。。。不废话了&#xff0c;上代码。。。package javaInnerclassDemo;class Link{class Node{private String name;private Node next;public Node(String name){this.namename;}public void setname(String name){this .name name;}p…

Python 写各大聊天系统的屏蔽脏话功能原理

来源&#xff1a;Cookie-Fei www.cnblogs.com/cookie1026/p/6121363.html突然想到一个视频里面弹幕被和谐的一满屏的*号觉得很有趣&#xff0c;然后就想用python来试试写写看&#xff0c;结果还真玩出了点效果&#xff0c;思路是首先你得有一个脏话存放的仓库好到时候检测&…

RHEL4- SAMBA服务(四)在x-window下图形界面简单搭建samba服务器

RHEL4- SAMBA服务&#xff08;四&#xff09;在x-window下图形界面简单搭建samba服务器在《RHEL4- SAMBA服务&#xff08;一&#xff09;samba服务的安装与启动》中我讲了如何安装和启动samba服务器&#xff0c;这一篇我来说一说如何使用图形界面配置简单的samba服务&#xff0…

通过图书编号查询python_文字版图书管理-python练习

"""2020-06-01 Python 打卡1、根据下面运行流程图和提示&#xff0c;实现文字版图书管理功能。提示&#xff1a;主体流程代码已实现如下&#xff0c;三个功能分别用函数来实现.每本图书用一个字典来存储&#xff1a;book1 {id:编号&#xff0c;name:书名&#x…

mvc identity连接mysql_asp.net MVC5,如何使用mysql数据库,使用MVC框架中自带的identity用户验证体系...

问题如题现在很多时候&#xff0c;即使是.net项目&#xff0c;我们用的数据库也未必时是 SQL Server了。但很多VS 自带的框架(如MVC 、WebAPI等框架)中的示例自带的仍然是默认Sql Server的&#xff0c;而且并不一定好改成别的数据库。这有时候就很苦恼。比如.net MVC框架中自带…

Dapr 知多少 | 分布式应用运行时

IntroDapr 官方团队已于最近&#xff08;2021.2.17&#xff09;正式发布Dapr v1.0&#xff0c;Dapr已正式生产可用&#xff0c;可以部署到自托管环境或 Kubernetes 集群。对于绝大多数开发者来说&#xff0c;想必对Dapr只是有所耳闻&#xff0c;而具体是什么&#xff08;What&a…

使用.NET中的XML注释(一) -- XML注释标签讲解

一.摘要 .Net允许开发人员在源代码中插入XML注释&#xff0c;这在多人协作开发的时候显得特别有用。 C#解析器可以把代码文件中的这些XML标记提取出来&#xff0c;并作进一步的处理为外部文档。 这篇文章将展示如何使用这些XML注释。 在项目开发中&#xff0c;很多人并不乐意写…

pythonpil库过滤图像contour_一秒钟带你走进P图世界-----(python)PIL库的使用

python-----PIL库的使用一、什么是PIL库1.PIL(Python Image Library)库是python语言的第三方库&#xff0c;具有强大的图像处理能力&#xff0c;不仅包含了丰富的像素、色彩操作功能&#xff0c;还可以用于图像的归档和批量处理能力。2.PIL库主要有2个方面的功能&#xff1a;(1…

mysql tddl_TDDL思考总结

单机数据库分布式数据库TDDL原理与最佳实践1. 数据库的结构1.1. KV存储(id是K)1.2. B树与红黑树B树的特点是叶子节点是块状&#xff0c;一个叶子里面有多个数据&#xff0c;相邻数据是存在一起的&#xff0c;123&#xff0c;456起等&#xff0c;而磁盘也是按块的&#xff0c;B树…