上一篇簡介了Controller如何安排程式邏輯流程、驗證參數,卻也發現了驗證參數導致程式寫得冗長不易維護,這一篇要介紹【FluentValidation】這個套件來解決這個問題。
安裝



設定
把之前的程式碼稍作整理,將Account與Password新建一個類型(Class)來封裝起來,原本Controller裡面的程式整理一下


自定義驗證Class
建立一個Class命名為UserSignUpParameterValidation

將UserSignUpParameter掛上Validator Attribute,意思是UserSignUpParameter請幫我用UserSignUpParameterValidation裡面的邏輯來驗證

帳號密碼不能為空值

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
public class UserSignUpParameterValidation:AbstractValidator<UserSignUpParameter> { public UserSignUpParameterValidation() {
RuleFor(x => x.Account) .NotEmpty() .WithMessage("帳號不能為Empty") .NotNull() .WithMessage("帳號不能為Null");
RuleFor(x=>x.Password) .NotEmpty() .WithMessage("密碼不能為Empty") .NotNull() .WithMessage("密碼不能為Null"); } }
|
RuleFor是FluentValidation提供的方法,意思是我為Account這個屬性建立驗證的Rule,而Rule分別是,NotEmpty(不能為空值)、NotNull(不能為Null),而緊接在每個驗證邏輯下面的WithMessage則是表示,當發生它上面的錯誤時,錯誤訊息請回傳這行。
接著我們可以將Controller的這塊驗證邏輯拿掉,交給UserSignUpParameterValidation專責處理就好。

帳號必須包含@字元,Password必須大於6個字
因為判斷字元@並不像判斷空值與Null一樣,官方有實做好的方法,必須自己透過Must來定義,這邊提供兩種寫法給讀者參考

上面是匿名方法的寫法,但如果你對於匿名委派還不是很熟悉,也可以用比較簡單的方式寫
[](https://4.bp.blogspot.com/-KmJSyZdiGb0/WvAWiccBedI/AAAAAAAAIvw/17gYP6xPzgIUFII1ptocXolNHkBXfGeegCLcBGAs/s1600/11.png)
先寫好驗證的方法,然後在Must中帶入方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
public class UserSignUpParameterValidation:AbstractValidator<UserSignUpParameter> { public UserSignUpParameterValidation() {
RuleFor(x => x.Account) .NotEmpty() .WithMessage("帳號不能為Empty") .NotNull() .WithMessage("帳號不能為Null") .Must(IncludeAccountKeyword) .WithMessage("帳號不符合格式");
RuleFor(x=>x.Password) .NotEmpty() .WithMessage("密碼不能為Empty") .NotNull() .WithMessage("密碼不能為Null") .MinimumLength(7) .WithMessage("密碼必須大於6個字元"); }
private bool IncludeAccountKeyword(string account) { if (!string.IsNullOrWhiteSpace(account)) { return account.Contains("@"); }
return false; } }
|
整理後的Controller

透過ModelState得知驗證結果
而因為開發習慣的關係,我習慣用FluentValidation的方式來取代原本ModelState驗證方法與設定方式,接著我們在Global.asax中呼叫FluentValidationModelValidatorProvider.Configure()

比較一下最一開始與套用FluentValidation後的程式碼,應該可以明顯感受到差異,這不僅僅只是讓程式變乾淨,更重要的是驗證參數的職責被分離到UserSignUpParameterValidation這個類別中,以後要改參數驗證的邏輯只要到這調整即可,不用再擔心Controller會被不小心改壞。