C# 中的 Fluent Validation - 功能强大而简单的数据验证工具
数据验证是可靠软件开发的支柱之一,在现代 .NET 应用程序中,您需要一种稳健、可维护和可扩展的方式来处理数据验证。 这就是 FluentValidation 的作用所在,它是一个流行的 .NET 库,用于构建强类型验证规则。
在他的深度视频教程"Fluent Validation in C# - The Powerful Yet Easy Data Validation Tool"中,Tim Corey 将带领观众一步步了解 FluentValidation 的使用过程。在本文中,我们将按照 Tim 的讲解,总结要点和代码示例,同时整合相关概念,如自定义验证器、连锁验证器、ASP.NET 集成以及对旧版运行时(如 .NET Core 3.1 和 .NET Standard 2.0)的支持。
简介:为什么选择 FluentValidation?
Tim 在视频开头解释了数据验证如何经常变得重复和混乱。 例如,在项目的不同部分复制和粘贴类似的验证规则就违反了 DRY(不要重复自己)原则。 因此,他介绍了 FluentValidation--一个免费、功能强大的 .NET 验证库,甚至可以在您不拥有的模型上运行,因此非常适合商业项目。
Tim 强调了学以致用的重要性,并指出观众可以通过他的每周挑战系列来培养技能。
演示应用程序概述
Tim 使用了一个 WinForms 演示应用程序,用户可以在其中输入
姓名
姓氏
账户余额
- 出生日期
虽然这是一个用户界面演示,但验证原则同样适用于 ASP.NET Core、API 测试,甚至控制台应用程序。
信任用户输入的危险
在这一点上,蒂姆提醒开发人员:"永远不要相信用户"。输入往往是不可预测的,例如输入 "ten "表示年龄,而不是 10。在将输入内容保存到数据库之前,必须对其进行验证。
他概述了验证规则示例:
名字和姓氏不能为空。
账户余额应遵循财务规则,如财务赞助的最低要求。
- 出生日期不能是未来的或超过 120 岁。
验证逻辑应置于何处?
Tim 探讨了配置验证器的选项:
用户界面表单内部
在模型类中使用数据注释
- 在使用 FluentValidation 的单独验证类中
他指出,数据注释是有限的,在使用外部库或需要更多自定义验证逻辑时往往不适用。
安装 FluentValidation
Tim 使用 Visual Studio,通过 NuGet 将 FluentValidation 添加到他的项目中。 他安装的是 8.1.0 版本,但指出 FluentValidation 是跨平台的,与以下版本兼容:
.NET Standard 2.0
.NET Core
ASP.NET
WPF
Xamarin
- 更多内容
Tim 的设置也适用于那些需要支持旧版运行时的人,包括支持 .NET Core 3.1 及更早版本的 FluentValidation 11。
创建验证器类
Tim 演示通过创建一个新类来构建强类型验证规则:
public class PersonValidator : AbstractValidator<Person>public class PersonValidator : AbstractValidator<Person>该类包含人员模型的所有验证逻辑。 使用流畅接口,在构造函数中定义验证规则。
第一条验证规则:名字
Tim 使用 lambda 表达式编写了一条规则:
RuleFor(p => p.FirstName).NotEmpty();RuleFor(p => p.FirstName).NotEmpty();他使用一个 var 验证器来验证 Person 对象:
var validator = new PersonValidator();
ValidationResult results = validator.Validate(person);var validator = new PersonValidator();
ValidationResult results = validator.Validate(person);然后,他循环检查所有验证失败,在列表框中显示用户友好的信息。
字符串长度和自定义消息
Tim 扩展了验证规则:
RuleFor(p => p.FirstName)
.NotEmpty().WithMessage("First name is empty")
.Length(2, 50).WithMessage("Length of first name is invalid");RuleFor(p => p.FirstName)
.NotEmpty().WithMessage("First name is empty")
.Length(2, 50).WithMessage("Length of first name is invalid");使用链式验证器,该规则可确保名称既不会是空的,也不会太短/太长。 Tim 介绍了 Cascade(CascadeMode.Stop),用于在第一次验证失败时停止验证。
自定义验证:名称中的有效字符
Tim 使用一个名为.NET 的方法实现了一个自定义验证器:
private bool BeAValidName(string name)private bool BeAValidName(string name)因此,在翻译过程中,我们采用了 "Unicode "技术,将空格和破折号去掉,并确保字符串只包含 Unicode 字母,从而支持国际字符。
自定义规则是这样应用的
.Must(BeAValidName).WithMessage("{PropertyName} contains invalid characters");.Must(BeAValidName).WithMessage("{PropertyName} contains invalid characters");这种方法结构非常适合适应其他字段,例如自定义邮政编码验证逻辑功能:
private bool BeAValidPostcode(string postcode)
{
// Add custom logic here to specify a valid postcode format
}private bool BeAValidPostcode(string postcode)
{
// Add custom logic here to specify a valid postcode format
}然后,您可以将其用于类似的验证器中:
RuleFor(c => c.Postcode).Must(BeAValidPostcode)
.WithMessage("Please specify a valid postcode");RuleFor(c => c.Postcode).Must(BeAValidPostcode)
.WithMessage("Please specify a valid postcode");这在需要公共类 CustomerValidator 或其他特定领域验证器的商业项目中很常见。
在错误消息中使用内置变量
Tim 演示了如何使用占位符动态增强信息,如
{PropertyName}
{总长度}
- {最小长度}和 {最大长度}
这就导致了上下文错误信息,如
"Length of First Name is invalid (was 105)""Length of First Name is invalid (was 105)"这将使用户更容易纠正输入错误。
姓氏和本地化
Tim 将 FirstName 的验证逻辑复制到 LastName,这要归功于 {PropertyName} 的可重用格式化。 他还提到了 WithLocalizedMessage() 用于 ASP.NET 或 需要多语言支持的全球应用程序。
重要:CascadeMode 是特定于规则的
Tim 澄清说,CascadeMode.Stop 适用于单个规则,而不是整个模型的全局规则。 如果 FirstName 和 LastName 都为空,即使设置了 CascadeMode,也会触发这两条规则。
出生日期验证
接下来,Tim 添加了一条规则,以确保 出生日期符合实际情况:
private bool BeAValidAge(DateTime dob)
{
var currentYear = DateTime.Now.Year;
var dobYear = dob.Year;
return dobYear <= currentYear && dobYear > (currentYear - 120);
}private bool BeAValidAge(DateTime dob)
{
var currentYear = DateTime.Now.Year;
var dobYear = dob.Year;
return dobYear <= currentYear && dobYear > (currentYear - 120);
}像这样使用:
RuleFor(p => p.DateOfBirth)
.Must(BeAValidAge)
.WithMessage("Invalid {PropertyName}");RuleFor(p => p.DateOfBirth)
.Must(BeAValidAge)
.WithMessage("Invalid {PropertyName}");对于验证日期或到期窗口等时间数据,这是一种很好的模式。
最终想法和建议
最后,Tim 总结了 FluentValidation 的主要优势:
集中验证逻辑
易于创建自定义验证器
与 .NET 5 及更新和更旧的运行时兼容
支持复杂模型、列表和异步规则
- 业余爱好者和商业项目的理想选择
他鼓励观众探索FluentValidation文档中的高级用法,包括嵌套规则、电子邮件属性验证等。
结论
FluentValidation 使 .NET 开发人员能够构建可重用、具有表现力和可维护性的强类型验证规则。 无论您是使用 .NET Core、.NET 8 进行开发,还是在 .NET Core 3.1 上维护传统系统,该库都能让数据验证变得轻而易举。
具有以下功能
用于构建规则的流畅界面
支持自定义邮编验证逻辑
与 Visual Studio 轻松集成
与 API 测试、WinForms 和 ASP.NET 兼容
- 稳健处理验证失败
FluentValidation 是您 .NET 工具包中的必备工具。 欲了解更多详情,请观看完整的 视频,并订阅 Tim 的 频道,了解更多关于 C# 的精辟视频。
提示:如果您是使用 FluentValidation 的新手,请尝试为公共字符串 Name、字符串 Postcode 等属性实施自己的 CustomerValidator 规则。 使用模拟 API 或 UI 表单进行测试,以获得实践经验。

