Appearance
FluentValidation 模型验证实践
在业务开发中,数据模型的验证通常会充斥着大量的
if (model.Name == null)。FluentValidation 是 .NET 下最优雅的模型验证框架之一,支持链式操作和规则集分离,能有效将“业务数据校验逻辑”从 Controller 或 Service 内部剥离出来。
一、 为什么使用 FluentValidation
相比 .NET 自带的 DataAnnotation(在属性上打 [Required] 等标签),FluentValidation 的优势在于:
- 解耦:验证规则单独成类,不污染实体模型(Entity / DTO)。
- 灵活:可以为同一个模型在不同场景下写不同的验证规则。
- 链式调用:支持丰富的条件逻辑(如:当 A 字段等于某值时,B 字段才必填)。
二、 基础使用流程
1. 引入依赖
最简单的方法是通过 NuGet 安装:
bash
Install-Package FluentValidation如果在 ASP.NET Core 中使用,建议安装扩展包,它能自动与 MVC 的模型绑定集成:
bash
Install-Package FluentValidation.AspNetCore2. 创建验证器
定义一个继承自 AbstractValidator<T> 的类,在构造函数中编写规则:
csharp
public class Customer
{
public int Id { get; set; }
public string Surname { get; set; }
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
// 规则链:不为空,且不等于特定字符串
RuleFor(customer => customer.Surname)
.NotNull().WithMessage("{PropertyName} 不能为空")
.NotEqual("foo").WithMessage("不能使用 foo");
}
}3. 执行验证
可以通过 Validate 方法获取验证结果对象:
csharp
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult result = validator.Validate(customer);
if (!result.IsValid)
{
foreach(var failure in result.Errors)
{
Console.WriteLine($"属性 {failure.PropertyName} 错误: {failure.ErrorMessage}");
}
}也可以通过 ValidateAndThrow 快速失败(直接抛出 ValidationException):
csharp
validator.ValidateAndThrow(customer);三、 常见高级场景
1. 集合验证 (RuleForEach)
当需要对集合中的每一个元素进行检查时:
csharp
public class Person
{
public List<string> AddressLines { get; set; } = new List<string>();
}
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
// 验证集合里的每一个元素都不为 null
RuleForEach(x => x.AddressLines).NotNull();
}
}2. 复杂对象与嵌套验证 (SetValidator)
当对象内部嵌套了另一个对象,可以复用另一个验证器:
csharp
public class AddressValidator : AbstractValidator<Address>
{
public AddressValidator()
{
RuleFor(address => address.Postcode).NotNull();
}
}
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.Name).NotNull();
// 嵌套验证
RuleFor(customer => customer.Address).SetValidator(new AddressValidator());
}
}如果是对象集合,也可以结合使用:
csharp
RuleFor(x => x.Orders).SetCollectionValidator(new OrderValidator());3. 规则集 (RuleSet)
可以在一个验证器中分组,调用时指定只验证某一组规则:
csharp
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleSet("Names", () =>
{
RuleFor(x => x.Surname).NotNull();
RuleFor(x => x.Forename).NotNull();
});
RuleFor(x => x.Id).NotEqual(0);
}
}
// 调用时只验证 "Names" 组
var result = validator.Validate(person, ruleSet: "Names");
// 验证所有规则(包含默认和各组)
var resultAll = validator.Validate(person, ruleSet: "*");