使用FluentValidation只需要引入Aegis.Transfer
包即可,该包里包含了FluentValidation
的包。
启用RequestValidation 参数验证
在Component.deps.json
中的Services节点中确定包含了RequestValidation
。
创建第一个验证程序
若要为特定对象定义一组验证规则, 您需要创建一个从 AbstractValidator<T>
继承的类, 其中泛型T参数是要验证的类的类型。假设您有一个客户类别
public record AddCustomerRequest {
public int Id { get; init; }
public string Surname { get; init; }
public string Forename { get; init; }
public decimal Discount { get; init; }
public string Address { get; init; }
}
接下来自定义继承于 AbstractValidator 泛型类的验证器,然后在构造函数中使用 LINQ 表达式编写 RuleFor 验证规则。
public class AddCustomerRequestValidator : AbstractValidator<AddCustomerRequest> {
public AddCustomerRequest() {
RuleFor(customer => customer.Surname).NotNull();
}
}
链接规则写法
您可以将对象的同一属性用多个验证程序链在一起,以下代码将验证 Surname 属性不为 Null 的同时且不等于foo字符串。
public class AddCustomerRequestValidator : AbstractValidator<AddCustomerRequest> {
public CustomerValidator() {
RuleFor(customer => customer.Surname).NotNull().NotEqual("foo");
}
}
集合
当针对一个集合进行验证时,只需要定义集合项类型的规则即可,以下规则将对集合中的每个元素运行 NotNull 检查。
public class Person {
public List<string> AddressLines {get;set;} = new List<string>();
}
public class PersonValidator : AbstractValidator<Person> {
public PersonValidator() {
RuleForEach(x => x.AddressLines).NotNull();
}
}
复杂属性
验证程序可以用于复杂属性,假设您有两个类:客户和地址。
public class Customer {
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address {
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
}
然后定义一个基于地址的 AddressValidator 验证器件
public class AddressValidator : AbstractValidator<Address> {
public AddressValidator() {
RuleFor(address => address.Postcode).NotNull();
//etc
}
}
然后定义一个基于客户的 CustomerValidator 验证器件,对地址验证时使用地址验证器。
public class CustomerValidator : AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(customer => customer.Name).NotNull();
RuleFor(customer => customer.Address).SetValidator(new AddressValidator());
}
}
复杂列表验证
还可以在集合属性上使用验证程序,假设客户对象包含订单集合属性:
public class Customer {
public IList<Order> Orders { get; set; }
}
public class Order {
public string ProductName { get; set; }
public decimal? Cost { get; set; }
}
var customer = new Customer();
customer.Orders = new List<Order> {
new Order { ProductName = "Foo" },
new Order { Cost = 5 }
};
定义了一个 OrderValidator 验证器件:
public class OrderValidator : AbstractValidator<Order> {
public OrderValidator() {
RuleFor(x => x.ProductName).NotNull();
RuleFor(x => x.Cost).GreaterThan(0);
}
}
此验证程序可在 CustomerValidator 中通过 SetCollectionValidator 方法使用:
public class CustomerValidator : AbstractValidator<Customer> {
public CustomerValidator() {
RuleFor(x => x.Orders).SetCollectionValidator(new OrderValidator());
}
}
var validator = new CustomerValidator();
var results = validator.Validate(customer);
WithMessage 提示消息
通过在验证程序上调用 WithMessage 方法, 可以覆盖验证程序的默认验证错误消息:
RuleFor(customer => customer.Surname).NotNull().WithMessage("姓名不能为空");
错误提示中,可以通过 {PropertyName} 占位符替换属性名,这里的PropertyName会读取RuleFor的Customer
RuleFor(customer => customer.Surname).NotNull().WithMessage("{PropertyName}不能为空");
除了 {PropertyName} 占位符,框架还内置了:{PropertyValue}、{ComparisonValue}、{MinLength}、{MaxLength}和{TotalLength} 占位符,关于更多内置占位符,可以参阅官方文档。
默认情况下,错误消息会输出属性名称,以下规则验证错误时,输出 Surname 不能为空。
RuleFor(customer => customer.Surname).NotNull();
验证程序支持通过 WithName 方法来指定属性别名,以下代码输出姓名不能为空。
RuleFor(customer => customer.Surname).NotNull().WithName("姓名");