asp.net core web api 限制輸入、模型驗證


我想要在我的web api里限制一下模型的輸入,例如我的一個模型有一個title屬性,我不希望新創建title的長度超過20,我能想到的辦法只有在Controller的Action里加if語句,但這樣會讓Controller非常難看,也不利於后面新功能的擴展。

在我需要這個功能之前,我不知道這個功能叫模型驗證……還用小白提問話術百度了很久。感覺學編程可以只看書,學開發還需要有老師或者有經驗的開發者的幫助。真的非常感謝我看過的所有博客、視頻、教程等的作者,以及每一個願意犧牲自己寥寥無幾的休閑時間,來耐心的解決我提的小白問題,還有給我去百度查詢解決方案提供查詢的方向的朋友們,沒有你們,我這種沒有天賦,智商一般的學生,真的就只能Hello World了。

 

首先是官方文檔:

https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/validation?view=aspnetcore-3.1

 

官方文檔最開始的模型狀態驗證:

 

下面寫着web api Controller,在Controller之前加上[ApiController]這個標簽就能免去這個if語句了,我目前主要是學習web api,MVC還沒來得及學,所以這里先不管了。

 

然后看我們真正要用的功能:

 

原來直接在上面加Atrribute就行,看一下基本的Attribute類型:

內置特性

以下是一些內置驗證特性:

[CreditCard]:驗證屬性是否具有信用卡格式。

[Compare]:驗證模型中的兩個屬性是否匹配。

[EmailAddress]:驗證屬性是否具有電子郵件格式。

[Phone]:驗證屬性是否具有電話號碼格式。

[Range]:驗證屬性值是否在指定的范圍內。

[RegularExpression]:驗證屬性值是否與指定的正則表達式匹配。

[Required]:驗證字段是否不為 null。 請參閱 [Required] 屬性,獲取關於該特性的行為的詳細信息。

[StringLength]:驗證字符串屬性值是否不超過指定長度限制。

[Url]:驗證屬性是否具有 URL 格式。

[Remote]:通過在服務器上調用操作方法來驗證客戶端上的輸入。 請參閱 [Remote] 屬性,獲取關於該特性的行為的詳細信息。

在 System.ComponentModel.DataAnnotations 命名空間中可找到驗證特性的完整列表。

System.ComponentModel.DataAnnotations 命名空間(我們這里沒用到,先留下鏈接留着后續學習):

https://docs.microsoft.com/zh-cn/dotnet/api/system.componentmodel.dataannotations?view=netframework-4.8

 

我正在實現web api的翻頁(分頁)功能,我現在的需求是讓queryString里輸入的pageNumber或者叫pageIndex不小於1,我之前試過,如果輸入小於1的,就會報500錯誤,但這個顯然是個400錯誤,是他的請求是BadRequest,這個鍋不應該服務器來背。

我發現上面的Range特性似乎非常合適,所以我用Range這個Attribute來搞一下:

 

我讓PageNumber的范圍在1到int能表示的最大值。(int 的System類型是Int32,short是Int16,long是Int64,所以這里我選擇Int32)。

跑起來,測試一下:

 

StringQuery里,pageNumber給到-1,返回了400,錯誤信息也很清晰,達成了我們的期望。

我突然有一個新需求,我想自定義Error的輸出信息,畢竟后面這個2147483647也沒什么人用得到,我主要想突出頁碼不能小於1這個事情,當然它默認的errorMessage給出了最大最小范圍,我覺得它默認的error信息是比較好的,但我還是想自定義一個。這里就要用到ErrorMessage屬性:

 

測試一下:

 

PageNumber給到0,成功返回了我們自定義的錯誤信息。

 

感覺這個Attribute方式不是非常靈活,我們這里的需求是可以滿足,但萬一后面我們有更復雜的需求,我們要五彩斑斕的黑和五光十色的白,怎么辦?有沒有另外一種更靈活的方式?

官方文檔給出了另外兩種方式:

方式1:

方式2:

 

我打算使用方式2,所以我把當前的類繼承IValidatableObject接口,把前面的Range Attribute注釋掉。然后實現IValidatableObject接口的Validate方法:

 

到現在,我甚至連yield這個關鍵字都不知道是什么意思,因為我C#沒怎么學,沒辦法,急着畢業找工作,趕鴨子上架,大學欠下的基礎債只能慢慢補了。這個方法寫完后,我們運行測試一下:

 

是我們想要的結果。

應該還有更牛比更通用的方式,但我們這里先不試了,用到的時候再去學,現在強行學了感覺能記住的概率也不大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM