|從0到1的建立Web API專案| Model 驗證之再進化 — FluentValidation
上篇回顧:|從0到1的建立 Web API 專案|JWT 建立 + Swagger 搭配 JWT
上篇回顧:|從0到1的建立 Web API 專案|Session 設置
上篇回顧:|從0到1的建立 Web API 專案|Middleware 統一回傳格式
Server 在接收 Client 的資料時,Model 內的參數都會有各自的規則,例如:不得為空、只能為數字、最多100字、要是Email格式…等,驗證的規則可以在 Client 就規範好或者是傳回 Server 時檢查,而在 Server 時資料驗證就是資料格式的最後一道防線,這時會不會有個疑問?那我通通在 Server 驗證就好啦~問什麼需要 Client 與 Server 同時驗證呢?其實兩種驗證是有不一樣的效果的:
(1) Client 驗證:傳回 Server 前先驗證會有效減少 Request 的數量,不需要到呼叫 API 後回傳資訊才知道資料錯誤,能有效減少Server與Client之間的來回的時間成本。
(2) Server 驗證:在 Server 收到資料後驗證,能作為資料的最後一道防線,以防資料進入資料庫時錯誤,能有效減少 Server 與 DB 之間來回的時間成本。
那本篇說明的內容會以 Server 驗證為主,在介紹本篇主軸 FluentValidation前,我們先來認識 .NET 提供的一些驗證方法:
(1) [Required]:驗證欄位不是 null。
(2) [Phone]:驗證屬性具有電話號碼格式。
(3) [EmailAddress]:驗證屬性具有電子郵件格式。
(4) [Url]:驗證屬性是否具有 URL 格式。
(5) [StringLength]:驗證字串屬性值不超過指定的長度限制。
(6) [Range]:驗證屬性值是否落在指定的範圍內。
(7) [CreditCard]:驗證屬性是否具有信用卡格式。
(8) [Compare]:驗證模型中的兩個屬性是否相符。
(9) [RegularExpression]:驗證屬性值是否符合指定的正則運算式。
這幾是其中一角的驗證規則,詳細的驗證規則放在底下的參考2,有需要可以自行參閱。現在我們來實作看看 .NET 的驗證規則,先建立一個 Model 放入想要驗證的參數(我們這邊以登入 Model 為例),我們為帳號 Account 設立驗證規則為不得為空、帳號為信箱,密碼 Passwrod 設立驗證規則為不得為空、只能為8位數字,這時我們可以在 LoginDto 中放入上述條件,並用啟用 Swagger 後呼叫 LoginUser 會得到以下結果(圖一)。
回傳結果竟然是
400 "Request cannot be processed. Please contact a support."
不是應該人性化提醒參數上有哪些錯誤嗎?別緊張,我們在 Startup.cs 中的 ConfigureServices 需要加上一段 AddMvc(),用來攔截驗證的錯誤資訊並且針對錯誤訊息去做處理,再次啟用 Swagger 後呼叫 LoginUser 就可以看到當我們的參數沒有符合驗證時,會跑出錯誤提醒(圖二)。
那 .NET 原生的驗證方法就很好用了,為什麼我們還要介紹 FluentValidation 呢?在上面使用 .NET 原生的驗證方法時,我們可以看到驗證邏輯與 Model 會在同一個檔案下,使用 FluentValidation 就是希望將驗證邏輯與 Model 分開以方便進行管理,讓專案架構更簡單明瞭,FluentValidation 的驗證不同於 .NET 的方式,會獨立建立Validator,將驗證邏輯寫在 Validator 內,而需要驗證時透過 Validator來驗證。請先在 NuGet 裡下載組件 FluentValidation 與 FluentValidation.AspNetCore(圖三),並且在Startup.cs 內的 ConfigureServices 中註冊 FluentValidation。
註冊完後,我們建立一個 UserValidator 放入剛剛我們制定好的驗證規則(帳號 Account 設立驗證規則為不得為空、帳號為信箱,密碼 Passwrod 設立驗證規則為不得為空、只能為8位數字),再次啟用 Swagger 後呼叫 LoginUser 就可以看到當我們的參數沒有符合驗證時,會跑出錯誤提醒(圖四)。
FluentValidation 和 .NET 一樣有許多種驗證規則,詳細驗證規則舉幾個常用的例子放在下方程式碼內,如需要更詳細的請參閱底下的參考4。
FluentValidation 有個要特別注意的地方,如果 Model 內包含其他子 Model 時,Validator 就需要做一個連結,才能正常啟用驗證功能。我們建立兩個 Model,並將其中一個Model (ProductDto) 以參數的型態放入另一個Model (ProductCategoryDto)內,並建立分別的 Validator 寫入想要的驗證,且在ProductCategoryValidator 內放 ProductValidator (如兩個Validator之間沒有連結 ProductCategoryDto 內的ProductList 會無法驗證)。
再次啟用 Swagger 後,呼叫內有 ProductCategoryDto 的函式,就可以對子內容(ProductDto)進行驗證(圖五)。
以上 FluentValidation 介紹了驗證的方法與進階的子內容驗證方式,下一篇我們會說到如何對 Model 與資料表的內容做快速的轉換與對應,
那我們下一篇見~