在 .NET 中使用 FluentValidation 進行參數驗證

77492358bd52a9dd5ebdfb097343ef38.png

不用說,參數驗證很重要,無效的參數,可能會導致程序的異常。

如果使用Web API或MVC頁面,那么可能習慣了自帶的規則驗證,我們的控制器很干凈:

public class User
{[Required]public string FirstName { get; set; }[Required]public string LastName { get; set; }
}

這種很常見,但是今天我想給你一個更好的替代方案:FluentValidation, 通過這個庫,您可以流暢地定義用于對象驗證的復雜規則,從而輕松構建和理解驗證規則,您可以在?Github[1]?上找到這個項目。

安裝 FluentValidation

我新建了一個很簡單的.NET Core 的Web API 程序,只有一個接口是用戶注冊,入參是一個User類, 然后在Nuget中安裝?FluentValidation

創建第一個驗證

對于要驗證的每個類,必須創建其自己的驗證器,每個驗證器類都必須繼承AbstractValidator<T>,其中T是要驗證的類,并且所有驗證規則都在構造函數中定義。

最簡單的驗證是針對空值,如果要指定FirstName和LastName都不能為空,這個驗證器是這樣:

public class UserValidator : AbstractValidator<User>
{public UserValidator(){RuleFor(x => x.FirstName).NotEmpty();RuleFor(x => x.LastName).NotEmpty();}
}

就這些了,您已經創建了第一個驗證器,是不是超級簡單!

還有一些其他的規則,比如 MinimumLength,MaximumLength和Length,用于驗證長度,您可以把多個規則指定到一個字段,就像這樣:

public class UserValidator : AbstractValidator<User>
{public UserValidator(){RuleFor(x => x.FirstName).NotEmpty();RuleFor(x => x.FirstName).MinimumLength(3);RuleFor(x => x.FirstName).MaximumLength(20);RuleFor(x => x.LastName).NotEmpty();}
}

驗證入參

我們之前已經定義了驗證規則,現在開始使用它,您只需要new 一個UserValidator對象,然后調用Validate方法, 它會返回一個對象,其中包含了驗證狀態和所有沒有通過驗證的信息。

[HttpPost]
public IActionResult Register(User newUser)
{var validator = new UserValidator();var validationResult = validator.Validate(newUser);if (!validationResult.IsValid){return BadRequest(validationResult.Errors.First().ErrorMessage);}return Ok();
}

如果我運行程序,然后輸入一個超長的名字:

{"FirstName": "趙錢孫李周吳鄭王馮陳褚衛蔣沈韓楊朱秦尤許何呂施張","LastName": "張"
}

我會收到驗證錯誤:"The length of 'First Name' must be 20 characters or fewer. You entered 24 characters"。

好吧,我不喜歡這個消息,那么你可以自定義錯誤消息,這很簡單,您可以使用 WithMessage 方法。

- RuleFor(x => x.FirstName).MaximumLength(20);
+ RuleFor(x => x.FirstName).MaximumLength(20).WithMessage("您的名字長度已經超出了限制!");

流利驗證

你可以把驗證規則,改成下邊這樣:

- RuleFor(x => x.FirstName).NotEmpty();
- RuleFor(x => x.FirstName).MinimumLength(3);
+ RuleFor(x => x.FirstName).NotEmpty().MinimumLength(3);

然后也可以把驗證規則應用于其他的屬性,就像這樣:

public UserValidator()
{RuleFor(x => x.FirstName).MaximumLength(20).WithMessage("您的名字長度已經超出了限制!").NotEmpty().MinimumLength(3);RuleFor(x => x.LastName).NotEmpty();
}

常見的驗證規則

這個庫有很多現成的基本類型驗證規則, 對于字符串,您可以使用不同的方法,比如 EmailAddress,IsEnumName(檢查值是否在指定的Enum類型中定義)和 InclusiveBetween, 檢查該值是否在定義的范圍內。

現在,我在User類添加了另外兩個字段,Password 和 ConfirmPassword。

Password字段是一個字符串,有效的長度必須在5到15個字符之間,并且要符合正則,為了定義是否滿足安全規則,我定義了一個HasValidPassword方法,它會返回一個bool值。

private bool HasValidPassword(string pw)
{var lowercase = new Regex("[a-z]+");var uppercase = new Regex("[A-Z]+");var digit = new Regex("(\\d)+");var symbol = new Regex("(\\W)+");return (lowercase.IsMatch(pw) && uppercase.IsMatch(pw) && digit.IsMatch(pw) && symbol.IsMatch(pw));
}

然后在密碼驗證中使用:

RuleFor(x => x.FirstName).MaximumLength(20).WithMessage("您的名字長度已經超出了限制!").NotEmpty().MinimumLength(3);RuleFor(x => x.LastName).NotEmpty();RuleFor(x => x.Password).Length(5, 15).Must(x => HasValidPassword(x));

還可以簡化一些:

RuleFor(x => x.Password).Length(5, 15)
-            .Must(x => HasValidPassword(x));
+            .Must(HasValidPassword);}

ConfirmPassword字段的唯一要求是等于Password字段:

RuleFor(x => x.ConfirmPassword).Equal(x => x.Password).WithMessage("2次密碼不一致!");

注入驗證器

修改Startup類中的ConfigureServices方法:

public void ConfigureServices(IServiceCollection services)
{services.AddControllers().AddFluentValidation();services.AddTransient<IValidator<User>, UserValidator>();
}

注意:這個地方的生命周期是 Transient。

這樣,在調用注冊接口的時候,會自動進行規則驗證:

[HttpPost]
public IActionResult Register(User newUser)
{return Ok();
}

然后,我們再嘗試傳入參數來調用接口:

{"FirstName": "趙錢孫李周吳鄭王馮陳褚衛蔣沈韓楊朱秦尤許何呂施張","LastName": "張"
}

很明顯,驗證不通過,接口會返回這樣的錯誤信息:

{"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1","title": "One or more validation errors occurred.","status": 400,"traceId": "|c4523c02-4899b7f3df86a629.","errors": { "FirstName": ["您的名字長度已經超出了限制!"]}
}

希望對您有幫助,您可以在官方文檔中找到更多的用法。

[1]?Github:?"https://github.com/FluentValidation/FluentValidation"
[2]?https://www.code4it.dev/blog/fluentvalidation:?"https://www.code4it.dev/blog/fluentvalidation"

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282384.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282384.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282384.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在win10系統下怎樣快速切換任務視圖

2019獨角獸企業重金招聘Python工程師標準>>> 切換窗口&#xff1a;Alt Tab 任務視圖&#xff1a;Win Tab (松開鍵盤界面不會消失) 切換任務視圖&#xff1a;Win Ctrl 左/右 創建新的虛擬桌面&#xff1a;Win Ctrl D 關閉當前虛擬桌面&#xff1a;Win Ctrl F4…

uwp應用在debug模式下運行正常,編譯為release版本的時候拋出異常

原因是在代碼中使用了dynamic關鍵字&#xff0c;導致release時.net native優化了代碼造成元數據丟失 所以在代碼中要盡量不用dynamic。轉載于:https://www.cnblogs.com/poison/p/7532142.html

Linux上搭建Samba,實現windows與Linux文件數據同步

一 環境介紹 1. 本地win10 2. Linux (centos7.4) 注&#xff1a;因為運營商方面禁止smb協議&#xff0c;導致無法在云服務器上使用smb&#xff0c;如果不是在虛擬機上操作&#xff0c;而是在云服務器上操作&#xff0c;建議還是使用 filezillaxshell組合 或者 使用finalshell等…

A5-1和DES兩個加密算法的學習

A5-1加密算法 1、基本原理 A5-1加密算法是一種流password&#xff0c;通過密鑰流對明文進行加密。然后用密鑰流進行對密文的解密操作。 這樣的算法主要用于GSM加密。也就是我們平時打電話的時候。通信數據發送到基站&#xff0c;基站發送到還有一個基站&#xff0c;基站發送到接…

從0到1簡易區塊鏈開發手冊V0.3-數據持久化與創世區塊

Author: brucefeng Email: brucefengbrucefeng.com 編程語言:Golang 1.BoltDB簡介 Bolt是一個純粹Key/Value模型的程序。該項目的目標是為不需要完整數據庫服務器&#xff08;如Postgres或MySQL&#xff09;的項目提供一個簡單&#xff0c;快速&#xff0c;可靠的數據庫。 Bolt…

ELK之elasticsearch5.6的安裝和head插件的安裝

這里選擇的elasticsearch為5.6的新版本&#xff0c;根據官方文檔有幾種暗裝方式&#xff1a; https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html 這里選擇rpm包安裝https://www.elastic.co/guide/en/elasticsearch/reference/curre…

Nginx 基礎(一)

一 、Nginx簡述 Nginx是一個開源、高性能、可靠的HTTP中間件、代理服務。二 、常見的HTTP服務 1. HTTPD-Apache基金會 2. IIS-微軟 3. GWS-Google 4. Nginx三、為什么選擇Nginx 原因一&#xff1a;IO多路復用epoll &#xff08;主要解決了并發性的問題&#xff09; 注1&#xf…

Ajax基本案例詳解之load的實現

Ajax的load實現&#xff1a; 看這篇之前建議大家去看看前面兩篇文章&#xff1a; 1.Ajax基本案例詳解之$.ajax的實現 2.Ajax基本案例詳解之$.get的實現 現在寫一下$.load()里面的主要內容&#xff1a; $("#semail").load("doindex.jsp","email1&q…

ASP.NET Core高性能服務器HTTP.SYS

如果我們只需要將ASP.NET CORE應用部署到Windows環境下&#xff0c;并且希望獲得更好的性能&#xff0c;那么我們選擇的服務器類型應該是HTTP.SYS。Windows環境下任何針對HTTP的網絡監聽器/服務器在性能上都無法與HTTP.SYS比肩。[本文節選《ASP.NET Core 6框架揭秘》第18章]一、…

神經網絡- receptive field

記錄一下感受野的理解&#xff1a; 在神經網絡中&#xff0c;感受野的定義是&#xff1a; 神經網絡的每一層輸出的特征圖&#xff08;Feature ap&#xff09;上的像素點在原圖像上映射的區域大小。 1. 神經網絡中&#xff0c;第一個卷積層的 感受野大小&#xff0c;就等于filt…

734. [網絡流24題] 方格取數問題 二分圖點權最大獨立集/最小割/最大流

問題描述&#xff1a;在一個有m*n 個方格的棋盤中&#xff0c;每個方格中有一個正整數。現要從方格中取數&#xff0c;使任意2 個數所在方格沒有公共邊&#xff0c;且取出的數的總和最大。試設計一個滿足要求的取數算法。編程任務&#xff1a;對于給定的方格棋盤&#xff0c;按…

Nginx 基礎 ( 二)

一、HTTP請求 http請求包括客戶端請求服務端 以及 服務端響應數據回客戶端&#xff0c;如下 請求&#xff1a;包括請求行、請求頭部、請求數據 響應&#xff1a;包括狀態行、消息報頭、響應正文 比如在Linux中curl請求網站獲取請求信息和響應信息 curl -v http://www.kugou.com…

《金融行業應用解決方案白皮書》發布,金融自主創新未來可期!

日前&#xff0c;以“聚勢賦能 行業共創”為主題的金融行業解決方案發布會在線上舉行。麒麟軟件發布《金融行業應用解決方案白皮書》&#xff0c;并發起成立“金融機具生態圈俱樂部”&#xff0c;助力金融行業用戶高質量發展。金融信息系統曾經被國外廠商壟斷金融信息系統作為國…

leetcode53 Maximum Subarray 最大連續子數組

題目要求 Find the contiguous subarray within an array (containing at least one number) which has the largest sum.For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous subarray [4,-1,2,1] has the largest sum 6.即&#xff1a;尋找數列中的一個子…

黑馬程序員-WEB前端與移動開發就業班

Web前端 — IT互聯網的“門面”有人的地方就有江湖&#xff0c;有網站的地方就有Web前端&#xff0c;無所不用&#xff0c;互聯網大勢所在。課程循序漸進&#xff0c;技術小白課快速上手課程結構由淺入深&#xff0c;基礎課程講解充分&#xff0c;了解網頁的結構組成、分析頁面…

詳解go語言的array和slice 【二】

上一篇 詳解go語言的array和slice 【一】已經講解過,array和slice的一些基本用法&#xff0c;使用array和slice時需要注意的地方&#xff0c;特別是slice需要注意的地方比較多。上一篇的最后講解到創建新的slice時使用第三個索引來限制slice的容量&#xff0c;在操作新slice時…

詳解Objective-C的meta-class

2019獨角獸企業重金招聘Python工程師標準>>> 比較簡單的一篇英文&#xff0c;重點是講解meta-class。翻譯下&#xff0c;加深理解。 原文標題&#xff1a;What is a meta-class in Objective-C? 原文地址&#xff1a;http://www.cocoawithlove.com/2010/01/what-is…

Nginx 模塊的使用

Nginx模塊的使用,就是在Nginx配置文件中的http、server、location中添加參數&#xff0c;進行多一項或幾項處理一、 實現響應內容替換 1、sub_module二、Nginx的請求限制 1、連接頻率限制 limit_conn_module 2、請求頻率限制 limit_req_module 注: HTTP請求建立在一次…

Question | 網站被黑客掃描撞庫該怎么應對防范?

本文來自網易云社區在安全領域向來是先知道如何攻&#xff0c;其次才是防。針對題主的問題&#xff0c;在介紹如何防范網站被黑客掃描撞庫之前&#xff0c;先簡單介紹一下什么是撞庫。撞庫是黑客通過收集互聯網已泄露的用戶和密碼信息&#xff0c;生成對于的字典表&#xff0c;…

十倍程序員 | 使用 Source Generator 將 JSON 轉換成 C# 類

前言有時候&#xff0c;我們需要將通過 WebAPI 接收 JSON 字符串轉換成 C# 代碼。Visual Studio 提供了一個功能菜單可以輕松實現&#xff1a;執行完成后&#xff0c;它會將生成的代碼放在打開的的代碼窗口中。但是&#xff0c;如果有多個 JSON 字符串需要轉換&#xff0c;這個…