這篇文章主要介紹了基于.NET的FluentValidation數(shù)據(jù)驗(yàn)證實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
學(xué)習(xí)地址:官網(wǎng)文檔,更多更詳細(xì)的內(nèi)容可以看官方文檔。
FluentValidation 是一個(gè)基于 .NET 開發(fā)的驗(yàn)證框架,開源免費(fèi),而且優(yōu)雅,支持鏈?zhǔn)讲僮鳎子诶斫?,功能完善,還是可與 MVC5、WebApi2 和 ASP.NET CORE 深度集成,組件內(nèi)提供十幾種常用驗(yàn)證器,可擴(kuò)展性好,支持自定義驗(yàn)證器,支持本地化多語言。
要使用驗(yàn)證框架, 需要在項(xiàng)目中添加對 FluentValidation.dll 的引用,支持 netstandard2.0 庫和 .NET4.5 平臺,支持.NET Core 平臺,最簡單的方法是使用 NuGet 包管理器引用組件。我這里安裝的是9.2.0版本。
Install-Package FluentValidation
若要在 ASP.NET Core 中使用 FluentValidation 擴(kuò)展,可引用以下包:
Install-Package FluentValidation.AspNetCore
若要在 ASP.NET MVC 5 或 WebApi 2 項(xiàng)目集成, 可以使用分別使用 FluentValidation.Mvc5 和 FluentValidation.WebApi 程序包。
Install-Package FluentValidation.Mvc5
Install-Package FluentValidation.WebApi
創(chuàng)建第一個(gè)驗(yàn)證程序
若要為特定對象定義一組驗(yàn)證規(guī)則, 您需要創(chuàng)建一個(gè)從 AbstractValidator 繼承的類, 其中泛型T參數(shù)是要驗(yàn)證的類的類型。假設(shè)您有一個(gè)客戶類別:
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 泛型類的驗(yàn)證器,然后在構(gòu)造函數(shù)中使用 LINQ 表達(dá)式編寫 RuleFor 驗(yàn)證規(guī)則,使驗(yàn)證在。
using FluentValidation;
using NetCoreBasicLearning.Entity;
namespace NetCoreBasicLearning
{
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleFor(customer => customer.Surname).NotNull();
}
}
}
若要執(zhí)行驗(yàn)證程序,我們通過定義好的 CustomerValidator 驗(yàn)證器傳入實(shí)體類 Customer 即可。
該驗(yàn)證方法返回一個(gè) ValidationResult 對象,表示驗(yàn)證結(jié)果,ValidationResult 包含兩個(gè)屬性:IsValid屬性是布爾值, 它表示驗(yàn)證是否成功,Errors屬性包含相關(guān)驗(yàn)證失敗的詳細(xì)信息。
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},錯(cuò)誤信息:{t.ErrorMessage}");
}
return Content(str.ToString());
}
return View();
}
鏈接規(guī)則寫法
您可以將對象的同一屬性用多個(gè)驗(yàn)證程序鏈在一起,以下代碼將驗(yàn)證 Surname 屬性不為 Null 的同時(shí)且不等于foo字符串。
using FluentValidation;
using NetCoreBasicLearning.Entity;
namespace NetCoreBasicLearning
{
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleFor(customer => customer.Surname).NotNull().NotEqual("foo");
}
}
}
引發(fā)異常
如果驗(yàn)證失敗, 不想返回 ValidationResult 對象,而是想直接拋出異常,可通過調(diào)用驗(yàn)證器的 ValidateAndThrow 進(jìn)行驗(yàn)證。
如果驗(yàn)證失敗,將引發(fā)一個(gè) ValidationException 類型的異常,這個(gè)異??梢员簧蠈映绦虿东@,并從異常中找到詳細(xì)錯(cuò)誤信息。
Customer customer = new Customer();
CustomerValidator validationRules = new CustomerValidator();
validationRules.ValidateAndThrow(customer);
集合
當(dāng)針對一個(gè)集合進(jìn)行驗(yàn)證時(shí),只需要定義集合項(xiàng)類型的規(guī)則即可,以下規(guī)則將對集合中的每個(gè)元素運(yùn)行 NotNull 檢查。
public class Customer
{
public List OtherAddress { get; set; }
}
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleForEach(customer => customer.OtherAddress).NotEmpty();
}
}
如果要對list進(jìn)行進(jìn)行非空判斷可以如下:
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleFor(customer => customer.OtherAddress).NotEmpty();
}
}
復(fù)雜屬性
驗(yàn)證程序可以用于復(fù)雜屬性,假設(shè)您有兩個(gè)類:客戶和地址
public class Customer
{
public Adress Address { get; set; }
}
public class Adress
{
public string City { get; set; }
public string Province { get; set; }
}
然后定義一個(gè)基于地址的 AddressValidator 驗(yàn)證器件:
public class AdressValidator : AbstractValidator
{
public AdressValidator()
{
RuleFor(t => t.City).NotEmpty();
RuleFor(t => t.Province).NotEmpty();
}
}
然后定義一個(gè)基于客戶的 CustomerValidator 驗(yàn)證器件,對地址驗(yàn)證時(shí)使用地址驗(yàn)證器。
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleFor(t => t.Address).SetValidator(new AdressValidator());
}
}
如果不想要創(chuàng)建另一個(gè)驗(yàn)證器可以直接內(nèi)聯(lián)定義子規(guī)則:
RuleFor(t => t.Address.City).NotEmpty();
另外,還可以在集合屬性上使用驗(yàn)證程序,假設(shè)客戶對象包含地址集合屬性:
public class Customer
{
public List Address { get; set; }
}
此驗(yàn)證程序可在 CustomerValidator 中通過 SetCollectionValidator(在8.0版本以前) 方法使用,在8.0版本以及之后被棄用需要使用RuleForEach來驗(yàn)證:
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleForEach(t => t.Address).SetValidator(new AdressValidator());
//RuleFor(x => x.Address).SetCollectionValidator(new AdressValidator());在8.0版本及以后棄用
}
}
在編寫驗(yàn)證規(guī)則時(shí),可以通過 Where 關(guān)鍵字排除或者篩選不需要驗(yàn)證的對象。
public class CustomerValidator : AbstractValidator
{
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方法在線定義子集合元素的規(guī)則,從而不用再定義另一個(gè)驗(yàn)證器:
RuleForEach(t => t.Address).ChildRules(adderss => {
adderss.RuleFor(t => t.City).NotEmpty();
adderss.RuleFor(t => t.Province).NotEmpty();
}).NotEmpty();
支持規(guī)則集
規(guī)則集允許您將驗(yàn)證規(guī)則分組在一起,這些規(guī)則可以作為一個(gè)組一起執(zhí)行,而忽略其他規(guī)則:
我們可以把“姓”和“名”統(tǒng)一加在一個(gè)姓名規(guī)則集中。
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleSet("Name", () =>
{
RuleFor(t => t.Surname).NotEmpty();
RuleFor(t => t.Forename).NotEmpty();
});
}
}
規(guī)則集通過一般的 Validate 方法是不會執(zhí)行驗(yàn)證的,需要用如下方法進(jìn)行單獨(dú)的驗(yàn)證,這將復(fù)雜的驗(yàn)證器定義分解為較小的部分進(jìn)行驗(yàn)證,IncludeRuleSets 中可以傳入多個(gè)規(guī)則集名稱來執(zhí)行多個(gè)規(guī)則集的驗(yàn)證:
Customer customer = new Customer();
CustomerValidator validationRules = new CustomerValidator();
ValidationResult validationResult = validationRules.Validate(customer, options => options.IncludeRuleSets("Name"));
規(guī)則集通過一般的 Validate 方法是不會執(zhí)行驗(yàn)證的,需要用如下方法進(jìn)行單獨(dú)的驗(yàn)證,這將復(fù)雜的驗(yàn)證器定義分解為較小的部分進(jìn)行驗(yàn)證,IncludeRuleSets 中可以傳入多個(gè)規(guī)則集名稱來執(zhí)行多個(gè)規(guī)則集的驗(yàn)證:
還可以通過 IncludeRulesNotInRuleSet 方法或使用特殊名稱“默認(rèn)”(不區(qū)分大小寫)來執(zhí)行驗(yàn)證所有不屬于規(guī)則集的規(guī)則:
ValidationResult validationResult = validationRules.Validate(customer, options =>{ options.IncludeRulesNotInRuleSet(); options.IncludeRuleSets("Name"); } );
可以通過調(diào)用強(qiáng)制執(zhí)行所有規(guī)則,而不管它們是否在規(guī)則集中 IncludeAllRuleSets(這等效于using IncludeRuleSets("*"))。
同個(gè)類型的多個(gè)驗(yàn)證器
一個(gè)驗(yàn)證器可以包含多個(gè)其他的驗(yàn)證器,只要這些驗(yàn)證器都是驗(yàn)證統(tǒng)一類型的即可。這樣就可以拆分驗(yàn)證器,通過不同的需求組合在一起:
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
Include(new CustomerSurnameValidator());
Include(new CustomerForenameValidator());
}
}
public class CustomerSurnameValidator : AbstractValidator
{
public CustomerSurnameValidator()
{
RuleFor(t => t.Surname).NotEmpty();
}
}
public class CustomerForenameValidator : AbstractValidator
{
public CustomerForenameValidator()
{
RuleFor(t => t.Forename).NotEmpty();
}
}
繼承驗(yàn)證
從FluentValidation 9.2開始,如果您的對象屬性作為其他類的基類或接口,則可以為各個(gè)子類/實(shí)現(xiàn)器設(shè)置特定的子驗(yàn)證器,來驗(yàn)證這個(gè)屬性。我們的類設(shè)置如下:
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; }
}
驗(yàn)證器如下:
public class StoreValidator : AbstractValidator
{
public StoreValidator()
{
RuleFor(t => t.Peoples).NotNull().SetInheritanceValidator(t =>
{
t.Add(new CustomerValidator());
});
}
}
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
RuleFor(t => t.Address).NotEmpty();
}
}
覆蓋消息
通過在驗(yàn)證程序上調(diào)用 WithMessage 方法, 可以覆蓋驗(yàn)證程序的默認(rèn)驗(yàn)證錯(cuò)誤消息。錯(cuò)誤提示中,可以通過 {PropertyName} 占位符替換屬性名。除了 {PropertyName} 占位符,框架還內(nèi)置了:{PropertyValue}、{ComparisonValue}、{MinLength}、{MaxLength}和{TotalLength} 占位符,關(guān)于更多內(nèi)置占位符,可以參閱官方文檔。
RuleFor(customer => customer.Surname).NotNull().WithMessage("Please ensure you have entered your {PropertyName}");
驗(yàn)證程序支持通過 WithName 方法來指定屬性別名,以下代碼輸出姓名不能為空。請注意,這僅替換錯(cuò)誤消息中屬性的名稱。當(dāng)您檢查上的Errors集合時(shí)ValidationResult,此錯(cuò)誤仍將與一個(gè)名為的屬性相關(guān)聯(lián)Surname。如果要完全重命名該屬性,則可以使用OverridePropertyName方法。
RuleFor(customer => customer.Surname).NotNull().WithName("姓名");
條件
When 和 Unless方法可用于執(zhí)行滿足指定條件情況下的規(guī)則,例如只當(dāng)Surname屬性不為空的時(shí)候,才執(zhí)行前面的Name屬性的非空驗(yàn)證(Unless和When是相反的所以這邊只講When就行啦?。?/p>
RuleFor(t => t.Name).NotEmpty().When(t => !string.IsNullOrEmpty(t.Surname));
如果需要指定多個(gè)規(guī)則在相同的條件下才執(zhí)行驗(yàn)證,可以直接用頂級的When方法:
public class CustomerValidator : AbstractValidator
{
public CustomerValidator()
{
When(t => !string.IsNullOrEmpty(t.Surname), () => { RuleFor(t => t.Name).NotEmpty();//其他驗(yàn)證規(guī)則 });
}
}
通過在When方法后面追加一個(gè)Otherwise方法,可以執(zhí)行不滿足When中調(diào)整的驗(yàn)證規(guī)則,如下:
When(t => !string.IsNullOrEmpty(t.Surname), () => { RuleFor(t => t.Name).NotEmpty(); }).Otherwise(() => { RuleFor(t => t.Name).Equal("哈哈"); });
默認(rèn)情況下,F(xiàn)luentValidation會將條件應(yīng)用于對的同一調(diào)用中的所有先前的驗(yàn)證器RuleFor。比如下面這條代碼,如果Surname不為空,則對Name進(jìn)行非空和是否等于11的驗(yàn)證,否則不會對Name執(zhí)行這兩個(gè)驗(yàn)證:
RuleFor(t => t.Name).NotEmpty().Equal("11").When(t => !string.IsNullOrEmpty(t.Surname));
如果僅希望將條件應(yīng)用于緊接條件之前的驗(yàn)證器,則必須明確參數(shù)ApplyConditionTo.CurrentValidator,如下,只有Equal受到When方法的限制,NotEmpty不管When是否為true都會執(zhí)行的。
RuleFor(t => t.Name).NotEmpty().Equal("11").When(t => !string.IsNullOrEmpty(t.Surname), ApplyConditionTo.CurrentValidator);
設(shè)置級聯(lián)模式
有兩種聯(lián)級模式:
Continue (默認(rèn)設(shè)置)-始終調(diào)用規(guī)則定義中的所有驗(yàn)證器
Stop -驗(yàn)證程序失敗后立即停止執(zhí)行規(guī)則(僅在FluentValidation 9.1和更高版本中可用,在舊版本中,您可以改用StopOnFirstFailure)
通過如下代碼,可以在NotNull驗(yàn)證不通過的時(shí)候就停止驗(yàn)證,不再執(zhí)行NotEqual的驗(yàn)證。默認(rèn)是驗(yàn)證不通過,也繼續(xù)驗(yàn)證下去。
RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");
設(shè)置嚴(yán)重性級別
默認(rèn)情況下,如果這些規(guī)則失敗,則嚴(yán)重性為“錯(cuò)誤”??梢酝ㄟ^調(diào)用WithSeverity方法來更改。例如,如果我們希望將缺少的姓氏標(biāo)識為警告而不是錯(cuò)誤,則可以將上面的行修改為:
RuleFor(x => x.Surname).NotNull().WithSeverity(Severity.Warning):
在9.0及更高版本中,可以改用回調(diào),這也使您可以訪問正在驗(yàn)證的項(xiàng)目:
RuleFor(person => person.Surname).NotNull().WithSeverity(person => Severity.Warning);
定制驗(yàn)證器
之前我們都是使用內(nèi)置的驗(yàn)證器,如Equal、NotNull等等。
我們也可以自己定義驗(yàn)證器,實(shí)現(xiàn)自定義驗(yàn)證器的最簡單方法是使用Must方法,該方法在內(nèi)部使用PredicateValidator。假設(shè)我們有以下課程:
public class Person {
public IList Pets {get;set;} = new List();
}
為了確保我們的list屬性包含少于10個(gè)項(xiàng)目,我們可以這樣做:
public class PersonValidator : AbstractValidator{
public PersonValidator() {
RuleFor(x => x.Pets).Must(list => list.Count < 10)
.WithMessage("The list must contain fewer than 10 items");
}
}
為了使我們自己定義的驗(yàn)證器可以重用,我們可以將其包裝為可作用于任何List類型的擴(kuò)展方法。
public static class MyCustomValidators {
public static IRuleBuilderOptions<T, IList> ListMustContainFewerThan<T, TElement>(this IRuleBuilder<T, IList> ruleBuilder, int num) {
return ruleBuilder.Must(list => list.Count < num).WithMessage("The list contains too many items");
}
}
在這里,我們在上創(chuàng)建一個(gè)擴(kuò)展方法IRuleBuilder,并使用通用類型約束來確保此方法僅出現(xiàn)在對列表類型的智能感知中。在方法內(nèi)部,我們以與以前相同的方式調(diào)用Must方法,但是這次我們在傳入的RuleBuilder實(shí)例上調(diào)用它。我們還將要比較的項(xiàng)目數(shù)作為參數(shù)傳遞?,F(xiàn)在,我們的規(guī)則定義可以重寫為使用以下方法:
RuleFor(x => x.Pets).ListMustContainFewerThan(10);
我們還可以通過Custom方法來自定義驗(yàn)證器,它相比于Must的好處是允許針對同一規(guī)則返回多個(gè)錯(cuò)誤(通過context.AddFailure多次調(diào)用該方法)。
public class PersonValidator : AbstractValidator{
public PersonValidator() {
RuleFor(x => x.Pets).Custom((list, context) => {
if(list.Count > 10) {
context.AddFailure("The list must contain 10 items or fewer");
}
});
}
}
到此這篇關(guān)于基于.NET的FluentValidation數(shù)據(jù)驗(yàn)證實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān).NET FluentValidation數(shù)據(jù)驗(yàn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
來源:腳本之家
鏈接:https://www.jb51.net/article/199526.htm
申請創(chuàng)業(yè)報(bào)道,分享創(chuàng)業(yè)好點(diǎn)子。點(diǎn)擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!