当前位置: 首页 > 编程笔记 >

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

吴镜
2023-03-14
本文向大家介绍在.NET Core 中使用 FluentValidation 进行规则验证的方法,包括了在.NET Core 中使用 FluentValidation 进行规则验证的方法的使用技巧和注意事项,需要的朋友参考一下

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

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

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

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

安装 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#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|c4523c02-4899b7f3df86a629.",
  "errors": { 
    "FirstName": [
      "您的名字长度已经超出了限制!"
    ]
  }
}

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

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

到此这篇关于在.NET Core 中使用 FluentValidation 进行规则验证的文章就介绍到这了,更多相关.NET Core 规则验证内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!

 类似资料:
  • 本文向大家介绍thinkphp5.0自定义验证规则使用方法,包括了thinkphp5.0自定义验证规则使用方法的使用技巧和注意事项,需要的朋友参考一下 我们在用thinkphp5.0时候,经常要自定义验证规则,这个写法与tp以前的版本有所区别,小编今天带来大家一起来学习一下5.0下验证规则的使用方法。 在thinkphp5中定义$rule(验证规则)有两种方式 方式一: 方式二: 如果方式一自定义

  • 验证规则的定义通常有两种方式,如果你使用了验证器的话,通常通过rule属性定义验证规则,而如果使用的是独立验证的话,则是通过rule方法进行定义。 属性定义 属性定义方式仅限于验证器,通常类似于下面的方式: <?php namespace app\index\validate; use think\Validate; class User extends Validate { prot

  • 我试图在我的Codeigniter项目中创建一组表单验证规则,以便在第一组验证失败时,第二个验证集不应运行。 我在CI手册里找到了这个: 我知道我现在可以分别运行每个集合的验证($this- 问题是,当我使用$config数组时,当表单post失败时,错误不会添加到表单验证类中(因此不会显示)。当我不使用规则集,但只使用$this时,它确实添加并显示了错误- 当使用一组规则输入无效表单数据时,没有

  • 我想在Esper中编写一条规则,当过去15分钟内的步数为0且心率高于120时触发。我想出了以下规则: 我的心率类别有以下字段: 我的Steps类有以下字段: 我面临的问题是,我只想在过去15分钟内没有采取任何措施的情况下启动规则。现在,当两个步骤事件的步骤数相同时,它将激发。我知道我可能必须使用计时器。但是我不知道如何写这个规则。谁能帮帮我吗?

  • 问题内容: 在下面的IP地址验证中,我想查看它是否为有效的IP地址,我该如何使用以下内容 问题答案: 请改用锚点: 这些确保字符串的开头和结尾在正则表达式的开头和结尾匹配。(嗯,从技术上讲,您不需要起始锚,因为它在方法中是隐式的)。 然后,在尝试访问其结果之前,检查正则表达式是否确实匹配: 当然,这不是验证IP地址的好方法(请查看gnibbler的答案以找到合适的方法)。但是,正则表达式可用于检测

  • 我正在尝试验证密码字段是否存在。我想允许某人编辑用户,他们可能想更改用户密码,也可能不想更改用户密码。所以我想我可以使用Laravels验证规则,特别是“有时”规则来实现这一点。我有一套规则: 例如,对于其他字段,通常会有其他规则,而对于密码,则会有更严格的规则。如果传递的数据中存在密码字段,我希望这只应用min:8规则,但是如果我将密码字段留空,则会出现一个验证错误,表明密码字段是必需的。 我不