基于.NET的FluentValidation数据验证实现

学习地址:官方文档,更多更详细的内容可以看官方文档。

FluentValidation 是一个基于 .NET 开发的验证框架,开源免费,而且优雅,支持链式操作,易于理解,功能完善,还是可与 MVC5、WebApi2 和 ASP.NET CORE 深度集成,组件内提供十几种常用验证器,可扩展性好,支持自定义验证器,支持本地化多语言。

要使用验证框架, 需要在项目中添加对 FluentValidation.dll 的引用,支持 netstandard2.0 库和 .NET4.5 平台,支持.NET Core 平台,最简单的方法是使用 NuGet 包管理器引用组件。我这里安装的是9.2.0版本。

Install-Package FluentValidation

若要在 ASP.NET Core 中使用 FluentValidation 扩展,可引用以下包:

Install-Package FluentValidation.AspNetCore

若要在 ASP.NET MVC 5 或 WebApi 2 项目集成, 可以使用分别使用 FluentValidation.Mvc5 和 FluentValidation.WebApi 程序包。

Install-Package FluentValidation.Mvc5
Install-Package FluentValidation.WebApi

创建第一个验证程序

若要为特定对象定义一组验证规则, 您需要创建一个从 AbstractValidator<T> 继承的类, 其中泛型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;
using NetCoreBasicLearning.Entity;

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

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

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

public IActionResult Index(string id)
{
  Customer customer = new Customer();
  CustomerValidator validationRules = new CustomerValidator();
  ValidationResult validationResult = validationRules.Validate(customer);

  if (!validationResult.IsValid)
  {
    var str = new StringBuilder();
    foreach(var t in validationResult.Errors)
    {
      str.AppendLine($"属性:{t.PropertyName},错误信息:{t.ErrorMessage}");
    }
    return Content(str.ToString());
  }
  return View();
}

链接规则写法

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

using FluentValidation;
using NetCoreBasicLearning.Entity;

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

引发异常

如果验证失败, 不想返回 ValidationResult 对象,而是想直接抛出异常,可通过调用验证器的 ValidateAndThrow 进行验证。

如果验证失败,将引发一个 ValidationException 类型的异常,这个异常可以被上层程序捕获,并从异常中找到详细错误信息。

Customer customer = new Customer();
CustomerValidator validationRules = new CustomerValidator();
validationRules.ValidateAndThrow(customer);

集合

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

public class Customer
{
  public List<string> OtherAddress { get; set; }
}

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleForEach(customer => customer.OtherAddress).NotEmpty();
  }
}

如果要对list进行进行非空判断可以如下:

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

复杂属性

验证程序可以用于复杂属性,假设您有两个类:客户和地址

public class Customer
{
  public Adress Address { get; set; }
}
public class Adress
{
  public string City { get; set; }
  public string Province { get; set; }
}

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

public class AdressValidator : AbstractValidator<Adress>
{
  public AdressValidator()
  {
    RuleFor(t => t.City).NotEmpty();
    RuleFor(t => t.Province).NotEmpty();
  }
}

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

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleFor(t => t.Address).SetValidator(new AdressValidator());
  }
}

如果不想要创建另一个验证器可以直接内联定义子规则:

RuleFor(t => t.Address.City).NotEmpty();

另外,还可以在集合属性上使用验证程序,假设客户对象包含地址集合属性:

public class Customer
{
  public List<Adress> Address { get; set; }
 }

此验证程序可在 CustomerValidator 中通过 SetCollectionValidator(在8.0版本以前) 方法使用,在8.0版本以及之后被弃用需要使用RuleForEach来验证:

public class CustomerValidator : AbstractValidator<Customer>
{
   public CustomerValidator()
  {
    RuleForEach(t => t.Address).SetValidator(new AdressValidator());
    //RuleFor(x => x.Address).SetCollectionValidator(new AdressValidator());在8.0版本及以后弃用
  }
}

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

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleForEach(t => t.Address).Where(t => !string.IsNullOrEmpty(t.City)).SetValidator(new AdressValidator());
    //RuleFor(x => x.Address).SetCollectionValidator(new AdressValidator()).Where(t => !string.IsNullOrEmpty(t.City));在8.0版本及以后弃用
  }
}

从FluentValidation 8.5开始,您还可以使用以下ChildRules方法在线定义子集合元素的规则,从而不用再定义另一个验证器:

RuleForEach(t => t.Address).ChildRules(adderss => {
  adderss.RuleFor(t => t.City).NotEmpty();
  adderss.RuleFor(t => t.Province).NotEmpty();
}).NotEmpty();

支持规则集

规则集允许您将验证规则分组在一起,这些规则可以作为一个组一起执行,而忽略其他规则:

我们可以把“姓”和“名”统一加在一个姓名规则集中。

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleSet("Name", () =>
    {
      RuleFor(t => t.Surname).NotEmpty();
      RuleFor(t => t.Forename).NotEmpty();
    });
  }
} 

规则集通过一般的 Validate 方法是不会执行验证的,需要用如下方法进行单独的验证,这将复杂的验证器定义分解为较小的部分进行验证,IncludeRuleSets 中可以传入多个规则集名称来执行多个规则集的验证:

Customer customer = new Customer();
CustomerValidator validationRules = new CustomerValidator();
ValidationResult validationResult = validationRules.Validate(customer, options => options.IncludeRuleSets("Name"));

还可以通过 IncludeRulesNotInRuleSet 方法或使用特殊名称“默认”(不区分大小写)来执行验证所有不属于规则集的规则:

ValidationResult validationResult = validationRules.Validate(customer, options =>{ options.IncludeRulesNotInRuleSet(); options.IncludeRuleSets("Name"); } );

可以通过调用强制执行所有规则,而不管它们是否在规则集中 IncludeAllRuleSets(这等效于using IncludeRuleSets("*"))。

同个类型的多个验证器

一个验证器可以包含多个其他的验证器,只要这些验证器都是验证统一类型的即可。这样就可以拆分验证器,通过不同的需求组合在一起:

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    Include(new CustomerSurnameValidator());
    Include(new CustomerForenameValidator());
  }
}
public class CustomerSurnameValidator : AbstractValidator<Customer>
{
  public CustomerSurnameValidator()
  {
    RuleFor(t => t.Surname).NotEmpty();
  }
}
public class CustomerForenameValidator : AbstractValidator<Customer>
{
  public CustomerForenameValidator()
  {
    RuleFor(t => t.Forename).NotEmpty();
  }
}

继承验证

从FluentValidation 9.2开始,如果您的对象属性作为其他类的基类或接口,则可以为各个子类/实现器设置特定的子验证器,来验证这个属性。我们的类设置如下:

public class Store
{
  public People Peoples { get; set; }
}
public class Customer : People
{
  public string Address { get; set; }
}
public class People
{
  public string Name { get; set; }
}

验证器如下:

public class StoreValidator : AbstractValidator<Store>
{
  public StoreValidator()
  {
    RuleFor(t => t.Peoples).NotNull().SetInheritanceValidator(t =>
    {
       t.Add<Customer>(new CustomerValidator());
    });
  }
}
 public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    RuleFor(t => t.Address).NotEmpty();
  }
}

覆盖消息

通过在验证程序上调用 WithMessage 方法, 可以覆盖验证程序的默认验证错误消息。错误提示中,可以通过 {PropertyName} 占位符替换属性名。除了 {PropertyName} 占位符,框架还内置了:{PropertyValue}、{ComparisonValue}、{MinLength}、{MaxLength}和{TotalLength} 占位符,关于更多内置占位符,可以参阅官方文档。

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

验证程序支持通过 WithName 方法来指定属性别名,以下代码输出姓名不能为空。请注意,这仅替换错误消息中属性的名称。当您检查上的Errors集合时ValidationResult,此错误仍将与一个名为的属性相关联Surname。如果要完全重命名该属性,则可以使用OverridePropertyName方法。

RuleFor(customer => customer.Surname).NotNull().WithName("姓名");

条件

When 和 Unless方法可用于执行满足指定条件情况下的规则,例如只当Surname属性不为空的时候,才执行前面的Name属性的非空验证(Unless和When是相反的所以这边只讲When就行啦!):

RuleFor(t => t.Name).NotEmpty().When(t => !string.IsNullOrEmpty(t.Surname));

如果需要指定多个规则在相同的条件下才执行验证,可以直接用顶级的When方法:

public class CustomerValidator : AbstractValidator<Customer>
{
  public CustomerValidator()
  {
    When(t => !string.IsNullOrEmpty(t.Surname), () => { RuleFor(t => t.Name).NotEmpty();//其他验证规则 });
  }
}

通过在When方法后面追加一个Otherwise方法,可以执行不满足When中调整的验证规则,如下:

When(t => !string.IsNullOrEmpty(t.Surname), () => { RuleFor(t => t.Name).NotEmpty(); }).Otherwise(() => { RuleFor(t => t.Name).Equal("哈哈"); });

默认情况下,FluentValidation会将条件应用于对的同一调用中的所有先前的验证器RuleFor。比如下面这条代码,如果Surname不为空,则对Name进行非空和是否等于11的验证,否则不会对Name执行这两个验证:

RuleFor(t => t.Name).NotEmpty().Equal("11").When(t => !string.IsNullOrEmpty(t.Surname));

如果仅希望将条件应用于紧接条件之前的验证器,则必须明确参数ApplyConditionTo.CurrentValidator,如下,只有Equal受到When方法的限制,NotEmpty不管When是否为true都会执行的。

RuleFor(t => t.Name).NotEmpty().Equal("11").When(t => !string.IsNullOrEmpty(t.Surname), ApplyConditionTo.CurrentValidator);

设置级联模式

有两种联级模式:

  • Continue (默认设置)-始终调用规则定义中的所有验证器
  • Stop -验证程序失败后立即停止执行规则(仅在FluentValidation 9.1和更高版本中可用,在旧版本中,您可以改用StopOnFirstFailure)

通过如下代码,可以在NotNull验证不通过的时候就停止验证,不再执行NotEqual的验证。默认是验证不通过,也继续验证下去。

RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");

设置严重性级别

默认情况下,如果这些规则失败,则严重性为“错误”。可以通过调用WithSeverity方法来更改。例如,如果我们希望将缺少的姓氏标识为警告而不是错误,则可以将上面的行修改为:

RuleFor(x => x.Surname).NotNull().WithSeverity(Severity.Warning);

在9.0及更高版本中,可以改用回调,这也使您可以访问正在验证的项目:

RuleFor(person => person.Surname).NotNull().WithSeverity(person => Severity.Warning);

定制验证器

之前我们都是使用内置的验证器,如Equal、NotNull等等。

我们也可以自己定义验证器,实现自定义验证器的最简单方法是使用Must方法,该方法在内部使用PredicateValidator。假设我们有以下课程:

public class Person {
 public IList<Pet> Pets {get;set;} = new List<Pet>();
}

为了确保我们的list属性包含少于10个项目,我们可以这样做:

public class PersonValidator : AbstractValidator<Person> {
 public PersonValidator() {
  RuleFor(x => x.Pets).Must(list => list.Count < 10)
   .WithMessage("The list must contain fewer than 10 items");
 }
}

为了使我们自己定义的验证器可以重用,我们可以将其包装为可作用于任何List<T>类型的扩展方法。

public static class MyCustomValidators {
 public static IRuleBuilderOptions<T, IList<TElement>> ListMustContainFewerThan<T, TElement>(this IRuleBuilder<T, IList<TElement>> ruleBuilder, int num) {
  return ruleBuilder.Must(list => list.Count < num).WithMessage("The list contains too many items");
 }
}

在这里,我们在上创建一个扩展方法IRuleBuilder<T,TProperty>,并使用通用类型约束来确保此方法仅出现在对列表类型的智能感知中。在方法内部,我们以与以前相同的方式调用Must方法,但是这次我们在传入的RuleBuilder实例上调用它。我们还将要比较的项目数作为参数传递。现在,我们的规则定义可以重写为使用以下方法:

RuleFor(x => x.Pets).ListMustContainFewerThan(10);

我们还可以通过Custom方法来自定义验证器,它相比于Must的好处是允许针对同一规则返回多个错误(通过context.AddFailure多次调用该方法)。

public class PersonValidator : AbstractValidator<Person> {
 public PersonValidator() {
  RuleFor(x => x.Pets).Custom((list, context) => {
   if(list.Count > 10) {
    context.AddFailure("The list must contain 10 items or fewer");
   }
  });
 }
}

到此这篇关于基于.NET的FluentValidation数据验证实现的文章就介绍到这了,更多相关.NET FluentValidation数据验证内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • asp.net数据验证控件

    1.非空数据验证控件RequiredFiledValidator. 属性:ControlToValiata 指验证控件对哪一个控件进行验证.例如验证TextBox控件的ID属性txtPwd,只要将RequiredFiledValidator.控件的ControlToValidata属性设置为txtPwd.代码:this.RequiredFiledValidator1.ControlToValidata="txtPwd"; ErrorMessage属性:用于指定页面中使用Required

  • ASP.NET Core WebApi中使用FluentValidation验证数据模型的方法

    介绍 验证用户输入是一个Web应用中的基本功能.对于生产系统,开发人员通常需要花费大量时间,编写大量的代码来完成这一功能.如果我们使用FluentValidation构建ASP.NET Core Web API,输入验证的任务将比以前容易的多. FluentValidation是一个非常流行的构建强类型验证规则的.NET库. 配置项目 第一步:下载FluentValidation 我们可以使用Nuget下载最新的 FluentValidation 库 PM> Install-Package Fl

  • 基于ASP.NET Core数据保护生成验证token示例

    ASP.NET Core Data Protection 不仅提供了非对称加密能力,而且提供了灵活的秘钥存储方式以及一致的加解密接口(Protect与Unprotect).Session中用到了它,Cookie验证中用到了它,OpenIdConnect中也用到了它...当然你也可以在应用开发中使用它,比如这篇博文中就是用它生成激活帐户的验证token. 首先在 Startup.ConfigureServices() 中注册 DataProtection 服务(注入 IDataProtection

  • 基于.NET的FluentValidation数据验证实现

    学习地址:官方文档,更多更详细的内容可以看官方文档. FluentValidation 是一个基于 .NET 开发的验证框架,开源免费,而且优雅,支持链式操作,易于理解,功能完善,还是可与 MVC5.WebApi2 和 ASP.NET CORE 深度集成,组件内提供十几种常用验证器,可扩展性好,支持自定义验证器,支持本地化多语言. 要使用验证框架, 需要在项目中添加对 FluentValidation.dll 的引用,支持 netstandard2.0 库和 .NET4.5 平台,支持.NET

  • 基于JavaScript实现带数据验证和复选框的表单提交

    实现: 1.用户至少选中某项,即表示选中该行,同时该行的数据验证通过,表单提交:否则,不提交. html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>带数据验证和复选框的表单提交</title> <script src="../commonJqery/jquery-3.0.0.js&q

  • Yii基于CActiveForm的Ajax数据验证用法示例

    本文实例讲述了Yii基于CActiveForm的Ajax数据验证用法.分享给大家供大家参考,具体如下: 1. 视图定义form表单开启ajax验证 $form = $this->beginWidget('CActiveForm', array( 'id'=>'zdzone-form', 'enableAjaxValidation'=>true,//开启ajax验证 'enableClientValidation'=>true,//开启客户端验证,生成js 'action'=>

  • Yii2框架数据验证操作实例详解

    本文实例讲述了Yii2框架数据验证操作.分享给大家供大家参考,具体如下: 一.场景 什么情况下需要使用场景呢?当一个模型需要在不同情境中使用时,若不同情境下需要的数据表字段和数据验证规则有所不同,则需要定义多个场景来区分不同使用情境.例如,用户注册的时候需要填写email,登录的时候则不需要,这时就需要定义两个不同场景加以区分. 默认情况下模型的场景是由rules()方法申明的验证规则中使用到的场景决定的,也可以通过覆盖scenarios()方法来更具体地定义模型的所有场景,例如: public

  • ASP.NET Core 6.0 基于模型验证的数据验证功能

    目录 1 前言 1.1 数据验证的场景 1.2 本文的脉络 2 模型验证 2.1 介绍 2.2 基本使用 (1)自定义模型 (2)控制器代码 (3)测试 2.3 内置特性 3 自定义数据验证 3.1 介绍 3.2 前置准备 3.3 方案1:替换工厂 3.4 方案2:自定义过滤器 (1)自定义过滤器 (2)禁用默认过滤器 (3)启用自定义过滤器 3.5 测试 3.6 总结 4 源码解读 4.1 基本介绍 4.2 MvcServiceCollectionExtensions 4.3 ApiBehav

  • Asp.Net Core基于JWT认证的数据接口网关实例代码

    前言 近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求用Aps.Net Core做数据网关服务且基于JWT认证实现对前后端分离的数据服务支持,于是想到我一直做.Net开发,问我是否对.Net Core有所了解?能不能做个简单Demo出来看看?我说,分道扬镳之后我不是调用别人的接口就是提供接口给别人调用,于是便有了以下示例代码. 示例要求能演示获取Token及如何使用该Token访问数据资源,在Demo中实现

  • js中自定义react数据验证组件实例详解

    我们在做前端表单提交时,经常会遇到要对表单中的数据进行校验的问题.如果用户提交的数据不合法,例如格式不正确.非数字类型.超过最大长度.是否必填项.最大值和最小值等等,我们需要在相应的地方给出提示信息.如果用户修正了数据,我们还要将提示信息隐藏起来. 有一些现成的插件可以让你非常方便地实现这一功能,如果你使用的是knockout框架,那么你可以借助于Knockout-Validation这一插件.使用起来很简单,例如我下面的这一段代码: ko.validation.locale('zh-CN');

  • laravel 数据验证规则详解

    如下所示: return [ 'accepted' => '必须为yes,on,1,true', 'active_url' => '是否是一个合法的url,基于PHP的checkdnsrr函数,因此也可以用来验证邮箱地址是否存在', 'after:date' => '验证字段必须是给定日期后的值,比如required|date|after:tomorrow,通过PHP函数strtotime来验证', 'after_or_equal:date' => '大于等于', 'alpha'

  • 如何使用SpringBoot进行优雅的数据验证

    JSR-303 规范 在程序进行数据处理之前,对数据进行准确性校验是我们必须要考虑的事情.尽早发现数据错误,不仅可以防止错误向核心业务逻辑蔓延,而且这种错误非常明显,容易发现解决. JSR303 规范(Bean Validation 规范)为 JavaBean 验证定义了相应的元数据模型和 API.在应用程序中,通过使用 Bean Validation 或是你自己定义的 constraint,例如 @NotNull, @Max, @ZipCode , 就可以确保数据模型(JavaBean)的正确

  • Blazor实现数据验证

    Blazor 提供一组输入组件. 输入组件会将绑定字段数据处理到模型,并在提交窗体时验证用户输入.下表显示了可用的输入组件: EditForm EditForm 组件通过 EditContext 包装这些输入组件并协调验证过程. 创建 EditForm 时,可以使用 Model 参数指定要绑定到的模型实例. 验证通常是使用数据批注完成的,并且可以进行扩展. 若要启用基于数据批注的验证,请将 DataAnnotationsValidator 组件添加为 EditForm 的子组件. EditFor

随机推荐