博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在.NET Core 中使用 FluentValidation 进行规则验证
阅读量:4035 次
发布时间:2019-05-24

本文共 4364 字,大约阅读时间需要 14 分钟。

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

如果使用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
{ public UserValidator() { RuleFor(x => x.FirstName).NotEmpty(); RuleFor(x => x.LastName).NotEmpty(); }}

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

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

public class UserValidator : AbstractValidator
{ 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
, 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://jxudi.baihongyu.com/

你可能感兴趣的文章
[leetCode By Python]111. Minimum Depth of Binary Tree
查看>>
[LeetCode By Python]118. Pascal's Triangle
查看>>
[LeetCode By Python]121. Best Time to Buy and Sell Stock
查看>>
[LeetCode By Python]122. Best Time to Buy and Sell Stock II
查看>>
[LeetCode By Python]125. Valid Palindrome
查看>>
[LeetCode By Python]136. Single Number
查看>>
[LeetCode By MYSQL] Combine Two Tables
查看>>
python jieba分词模块的基本用法
查看>>
[CCF BY C++]2017.12 最小差值
查看>>
[CCF BY C++]2017-12 游戏
查看>>
如何打开ipynb文件
查看>>
[Leetcode BY python ]190. Reverse Bits
查看>>
Android下调用收发短信邮件等(转载)
查看>>
Android中电池信息(Battery information)的取得
查看>>
SVN客户端命令详解
查看>>
Android/Linux 内存监视
查看>>
Linux系统信息查看
查看>>
用find命令查找最近修改过的文件
查看>>
Android2.1消息应用(Messaging)源码学习笔记
查看>>
Phone双模修改涉及文件列表
查看>>