基于.NET的FluentValidation数据验证实现_实用技巧

来源:脚本之家  责任编辑:小易  

www.zgxue.com防采集请勿采集本网。

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

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.Mvc5Install-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数据验证内容请搜索真格学网以前的文章或继续浏览下面的相关文章希望大家以后多多支持真格学网! 您可能感兴趣的文章:ASP.NET Core WebApi中使用FluentValidation验证数据模型的方法基于ASP.NET Core数据保护生成验证token示例asp.net数据验证控件

在Nop中大2113量使用的验证方式,包括输入验5261证,后台数据判断,采用FluentValication库。4102A small validation library for .NET that uses a fluent interfaceand lambda expressions for building validation rules for your business objects.一个轻量型的.NTE验证库,通过Flucent接口以及Lambda表达式1653来为业务逻辑对象建立验证规则,例如为PresentatilonModel以及BusinessModel。从典型使用方式来看,首先引用FluentValidation/FluentValidation.MVC,然后就可以在代码中使用了:using FluentValidation;//Validator类public class CustomerValidator: AbstractValidator<Customer> { public CustomerValidator() { //设置各种规则,通过Lambda表达式, customer isvariable for type of Customer RuleFor(customer =>customer.Surname).NotEmpty(); RuleFor(customer =>customer.Forename).NotEmpty().WithMessage("Please specify a first name"); RuleFor(customer => customer.Company).NotNull(); RuleFor(customer =>customer.Discount).NotEqual(0).When(customer => customer.HasDiscount); RuleFor(customer =>customer.Address).Length(20, 250); RuleFor(customer =>customer.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode"); } private bool BeAValidPostcode(string postcode) { // custom postcode validating logic goes here }}//被验证对象Customer customer = new Customer();CustomerValidator validator = newCustomerValidator();//验证操作,结果存储在Results结构体中ValidationResult results = validator.Validate(customer);//成功/失败;以及错误消息列表bool validationSucceeded =results.IsValid;IList<ValidationFailure> failures = results.Errors; 本地化默认的FluentValidation提供的信息提示包含以下语言:* English* Dutch* French* German* Portuguese* Spanish那中文的话,就需要我们增加一些代码来处理:两种方式,使用WithLocalizedMessage方法去指定单个的验证规则的本地化错误消息;或设置全局ResourceProviderType来用自己定义的一套本地字符串替换FluentValidation的所有默认错误信息提示。 举个例子,通过指定ResourceType以及其属性名称SurnameRequiredError,实际代表一个资源文件的一个字符串。RuleFor(x => x.Surname).NotNull().WithLocalizedMessage(() => MyLocalizedMessage.SurnameRequiredError);需要主要的是这个Property需要是public并且Static的。 1. 打开项目,添加引用,然后增加目录Validator,添加Class类文件ProductValidator.cs2. 增加资源文件(特别注意点: CustomerTool: PublicResXFileCodeGenerator)(Custom Tool Namespace: HWResources)可以看到产生的属性: public static string NotEmptyString { get { return ResourceManager.GetString("NotEmpty", resourceCulture); }3. 完成验证代码:public class ProductValidator : AbstractValidator<Product> { public ProductValidator() { RuleFor(p => p.ProductID) .NotEmpty() .WithLocalizedMessage(() => HWResources.ServerSide.NotEmpty); } }使用自定义的ResourceProvider Type:这种方式适合批量替换默认消息,可以通过设置Validatoroptions类的ResourceProviderType属性ValidatorOptions.ResourceProviderType = typeof(MyResources); public class MyResources { public static stringnotempty_error { get { return"{PropertyName} 是必须输入的!"; } }}通过以上的方式,非空判断的默认的消息就会显示为xxx是必须输入的! 通过自定义的ResourceProvider类型,需要了解Fluent暴露出来的资源字符串名字:* email_error* equal_error* exact_length_error* exclusivebetween_error* greaterthan_error* greaterthanorequal_error* inclusivebetween_error* length_error* lessthan_error* lessthanorequal_error* notempty_error* notequal_error* notnull_error* predicate_error* regex_error 通过以上的学习,您可能会想起在Nop中有目录名为Validators其中有各个对象命名的子目录,其中又包含了XXXValidator.csnamespaceNop.Admin.Validators.Directory{ public class CountryValidator: AbstractValidator<CountryModel> { publicCountryValidator(ILocalizationServicelocalizationService) { RuleFor(x => x.Name) .NotNull() .WithMessage(localizationService.GetResource("Admin.Configuration.Countries.Fields.Name.Required"));其多语言就是通过withmessage()来实现的。当然关于使用validation在NOP中,还涉及如何在MVC中使用FluentValidation.这个仅仅是开篇 更多详细资料,请参考http://fluentvalidation.codeplex.com内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • asp.net网站优化系列之数据库的优化措施与索引优化方法
  • .net控件dropdownlist动态绑定数据具体过程分解
  • .net下实现数字和字符相混合的验证码实例
  • c# .net动态调用webservice实现思路及代码
  • 几个 asp.net 小技巧
  • asp.net(c#)自动执行计划任务的程序实例分析分享
  • asp.net实现直接在浏览器预览word、excel、pdf、txt文件(附源码
  • asp.net操作excel备忘录
  • asp.net(c#) string, stringbuilder 与 stringwriter性能比较
  • .net core 3.0之创建基于consul的configuration扩展组件
  • fluentvalidation mvc5怎么注销默认验证
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础应用实用技巧自学过程首页asp.net实用技巧asp.net core webapi中使用fluentvalidation验证数据模型的方法基于asp.net core数据保护生成验证token示例asp.net数据验证控件asp.net网站优化系列之数据库的优化措施与索引优化方法.net控件dropdownlist动态绑定数据具体过程分解.net下实现数字和字符相混合的验证码实例c# .net动态调用webservice实现思路及代码几个 asp.net 小技巧asp.net(c#)自动执行计划任务的程序实例分析分享asp.net实现直接在浏览器预览word、excel、pdf、txt文件(附源码asp.net操作excel备忘录asp.net(c#) string, stringbuilder 与 stringwriter性能比较.net core 3.0之创建基于consul的configuration扩展组件未将对象引用设置到对象的实例 (java正则表达式 pattern和matcheasp.net(c#)网页跳转七种方法小结未能加载文件或程序集“xxx”或它asp.net“服务器应用程序不可用”asp.net中的几种弹出框提示基本实asp.net gridview 72般绝技asp.net生成excel并导出下载五种asp.net对路径"xxxxx"asp.net汉字转拼音和获取汉字首字.net+js对用户输入内容进行字数提示功能的ashx文件的使用小结巧妙使用jquery clone 添加多行数据,并更利用aspose.cells实现万能导出功能asp.net在mvc中maxlength特性设置无效的解.net core下对于附件上传下载的实现示例asp.net2.0:页面中链入的css、js文件带中asp.net mvc中异常exception拦截的深入理获取创建membership的数据库创建脚本.net/c#如何判断某个类是否是泛型类型或泛
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved