数据校验 FluentValidation使用详解

47 篇文章 1 订阅

安装

//普通winform等用到的
Install-Package FluentValidation
//这是AspNetCore中用到的
Install-Package FluentValidation.AspNetCore

创建第一个认证

若要为特定对象定义一组验证规则, 您需要创建一个从 AbstractValidator 继承的类, 其中泛型T参数是要验证的类的类型。假设您有一个客户类别:

public class Customer 
{
  public int Id { get; set; }
  public string Surname { get; set; }
  public string Forename { get; set; }
  public decimal Discount { get; set; }
  public string Address { get; set; }
}

接下来自定义继承于 AbstractValidator 泛型类的验证器,然后在构造函数中使用 LINQ 表达式编写 RuleFor 验证规则。

using FluentValidation;

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleFor(customer => customer.Surname).NotNull();
  }
}

若要执行验证程序,我们通过定义好的 CustomerValidator 验证器传入实体类 Customer 即可。

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();

ValidationResult result = validator.Validate(customer);

该验证方法返回一个 ValidationResult 对象,表示验证结果,ValidationResult 包含两个属性:IsValid属性是布尔值, 它表示验证是否成功,Errors属性包含验证失败的详细信息。

下面的代码演示向控制台输出验证失败的详细信息:

using FluentValidation.Results; 

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();

ValidationResult results = validator.Validate(customer);

if(! results.IsValid) 
{
  foreach(ValidationFailure failure in results.Errors)
  {
    Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
  }
}

你可以收能够用tostring将所有的验证异常数据揉合在一起,默认情况下会分多行,你可以指定分隔符。

using FluentValidation;
using FluentValidation.Results;

Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();

ValidationResult results = validator.Validate(customer);

if (!results.IsValid)
{
    Console.WriteLine(results.ToString("~"));
}

链接规则写法

您可以将对象的同一属性用多个验证程序链在一起,以下代码将验证 Surname 属性不为 Null 的同时且不等于foo字符串。

using FluentValidation;

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleFor(customer => customer.Surname).NotNull().NotEqual("foo");
  }
}

集合

当针对一个集合进行验证时,只需要定义集合项类型的规则即可,以下规则将对集合中的每个元素运行 NotNull 检查。

public class Person
{
    public List<string> AddressLines { get; set; } = new List<string>();
}


public class PersonValidatior:AbstractValidator<Person>
{
    public PersonValidatior()
    {
        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 Country { get; set; }
  public string Postcode { get; set; }
}

然后定义一个基于地址的 AddressValidator 验证器件:

public class AddressValidator:AbstractValidator<Address>
{
    public AddressValidator()
    {
        RuleFor(address => address.Postcode).NotNull();
    }
}

然后定义一个基于客户的 CustomerValidator 验证器件,对地址验证时使用地址验证器。


public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor(customer => customer.Name).NotNull();
        RuleFor(customer => customer.Address).SetValidator(new AddressValidator());
    }
}

这时候你就可以运行CustomerValidator 的Validate,这会运行Customer以及Address的验证器,并将结果合在一起。

在编写验证规则时,可以通过 Where 关键字排除或者筛选不需要验证的对象。
customer.Address 为空的不再验证

RuleFor(customer => customer.Address.Postcode).NotNull().When(customer => customer.Address != null)

重写异常信息

你可以使用WithMessage 重写default的异常信息

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure that you have entered your Surname");

请注意WithMessage中也可以使用占位符,例如

RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure you have entered your {PropertyName}");

这里PropertyName将会被Surname替代。

通用占位符

如上所述,Validator可以包含占位符例如{PropertyName},这会在运行时被替换,每一种内置的验证器都有一系列的占位符,以下占位符在所有的类型的验证器中都可以使用

  • {PropertyName} 被验证的属性的属性名
  • {PropertyValue} 被验证的属性的属性值

比较类验证占位符(Equal, NotEqual, GreaterThan, GreaterThanOrEqual, etc.)

  • {ComparisonValue} 属性将要比对的值
  • {ComparisonProperty} 被用来比较的属性

Length 验证占位符

  • {MinLength} – Minimum length
  • {MaxLength} – Maximum length
  • {TotalLength} – Number of characters entered

验证指定属性

通过指定IncludeProperties 你可以运行validator中的特殊属性而不是所有属性都验证

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleFor(x => x.Surname).NotNull();
    RuleFor(x => x.Forename).NotNull();
    RuleForEach(x => x.Orders).SetValidator(new OrderValidator());
  }
}

//以下只会验证Surname
var validator = new CustomerValidator();
validator.Validate(new Customer(), options => 
{
  options.IncludeProperties(x => x.Surname);
});


RuleSets 规则集

规则集允许您将验证规则分组在一起,这些规则可以作为一个组一起执行,同时忽略其他规则。
例如我们有一个Person类,有三个属性 (Id, Surname, Forename)然后每个属性都有一个验证规则,我们将Surname 和Forename的验证规则组合成一个名为Names的验证集。

public class Person
{
    public int Id { get; set; }

    public string Surname { get; set; }

    public string Forename { get; set; }
}

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);
    }
}

我们可以通过向validator添加选项指定运行规则

var validator = new PersonValidator();
var person = new Person();
var result = validator.Validate(person, options => options.IncludeRuleSets("Names"));

这允许您将复杂的验证器定义分解为可以单独执行的更小的段。如果在没有传递规则集的情况下调用Validate,则只执行不在规则集中的规则。
你可以通过将多个规则集名称传递给inclerulesets来执行多个规则集:

var result = validator.Validate(person, options => 
{
  options.IncludeRuleSets("Names", "MyRuleSet", "SomeOtherRuleSet");
});

你也可以通过调用inclerulesnotinruleset来包含所有不属于规则集的规则,或者使用特殊名称“default”(不区分大小写):

validator.Validate(person, options => 
{
  // Option 1: IncludeRulesNotInRuleSet is the equivalent of using the special ruleset name "default"
  options.IncludeRuleSets("Names").IncludeRulesNotInRuleSet();
  // Option 2: This does the same thing.
  option.IncludeRuleSets("Names", "default");
});

设置级联模式(Cascade)

您可以设置级联模式,以自定义当验证器类中的特定规则或规则中的验证器失败时,FluentValidation如何执行规则和验证器。

默认情况,编写多个链式验证规则时,下无论前一个规则失败与否,后一个规则都将执行,以下代码检查 Surname 是否为空,然后检查 Surname 不等于零度,如多 NotNull 验证失败,则仍将调用 NotEqual 验证。

RuleFor(x => x.Surname).NotNull().NotEqual("零度");

我们可以通过 Stop方法制定级联模式。

public class Person
{
    public int Id { get; set; }

    public string Surname { get; set; }

    public string Forename { get; set; }
}

public class PersonValidator:AbstractValidator<Person>
{
    public PersonValidator()
    {

      RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().NotEqual("零度");
    }
}

Must自定义验证

我们还可以只用mast函数,指定自定义得验证器

using FluentValidation;
using FluentValidation.Results;
Customer customer = new Customer() { ID = 1, Name = "ellisvv" };

CustomerValidator validationRules = new CustomerValidator();


ValidationResult validationResult= validationRules.Validate(customer);
Console.WriteLine(validationResult.ToString());




public class Customer
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor(x => x.Name).Must(test).WithMessage("{PropertyName} must contains blank");
    }

    public bool test(string arg)
    {
        if(arg.Contains(" "))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

官网

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值