[水煮 ASP.NET Web API2 方法论](1-6)Model Validation
問題
? 想要?ASP.NET Web API?執行模型驗證,同時可以和?ASP.NET MVC?共享一些驗證邏輯。
解決方案
??ASP.NET Web API?與?ASP.NET MVC?支持一樣的驗證機制,都是通過System.ComponentModel.DataAnnoataions?的屬性驗證。使用框架提供的相關驗證屬性,已足夠來用來驗證模型。
想要更細粒度的驗證,我們可以選擇在我們的模型中實現?IValudateObject(來自于System.ComponentModel.DataAnnotations)。如果所有的屬性都驗證通過,ASP.NET Web API?將會調用接口的Validate?方法,在這里我們可以進行更進一步的進行實體驗證。這是和?MVC?里面的行為一樣,并且,我們甚至可以在?Web API?和?MVC?中使用同一個?DTO。
??還有另一種方法,就是可以使用一個叫做?FluentValidation(NuGet?中可以下載FluentValidation)的第三方程序庫,他可以構建更強大的驗證場景。在這樣的情況下,我們仍然需在我們的模型中實現?IValidateObject?接口,同時需要依賴于FluentValidation?驗證器,而不是內嵌的驗證邏輯。
小提示?ASP.NET Web API?的驗證行為在跨宿主機上是相同的。
工作原理
??為了從?HTTP?請求?Body?中讀取的模型并執行驗證,ASP.NET Web?API?依賴于一個?IBodyModelValidator?的服務。接口的大致描述如清單?1-17?所示,然而,他是一個可替代的服務,正常情況下,默認實現(DefaultBodyModelValidator)足夠我們使用,在HttpConfiguration?被設置為自啟動。
清單 1-17. IBodyModelValidator 接口
| 1 2 3 4 5 | public?interface?IBodyModelValidator { ????bool?Validate(object?model,?Type?type,?ModelMetadataProvider?metadataProvider, ????HttpActionContext?actionContext,?string?keyPrefix); } |
?
?
??有一個叫做FormatrtParameterBinding?的服務,在?HTTP?請求?Body?綁定到?Action?參數的處理請求時,DefaultBodyModelValidator?的?Validate?方法會被調用。對于驗證程序,他會遞歸驗證整個對象圖譜,驗證每一個屬性以及嵌套屬性。Web API?通過使用DataAnnotationModelValidatorProviderr?來支持聲明。如果我們的模型使用WCF?方式的?DataMemberAttribute?聲明,那么,我們需要使用框架的?DataMemberValidatorProvider。
??最后,我們的模型可以實現IValidatableObject?接口,這個接口只暴露了一個簡單的方法如清單1-18所示。如果實現了接口,那就需要我們自己提供額外的驗證邏輯。只要所有的屬性驗證通過,ASP.NET Wwb?API?就會調用IValidateableObject接口的?Validate?方法,
?
清單1-18. IValidateableObject 接口的定義
| 1 2 3 4 | public?interface?IValidateableObject { ????IEnumerable<ValidationResult>?Validate(ValidationContext?validationContext); } |
?
?
??驗證結果是通過?ASP.NET Web API?的??ModelStateDictionary?形式表示,在這里?ModelState?也是可以用的。這個和?ASP.NET MVC?中的概念是完全一樣的,但是使用的對象是不同的,因為?Web API?使用自己版本的System.Web.Http.Modelbinding。ModelStateDictionary?暴露了IsValid?屬性,這個屬性可以用來檢查?Action?內Model?驗證的狀態。
??聲明的驗證機制也很好的整合到了?ASP.NET Web API Help Page,可以提供對?API?語義上的描述。我們將會在7-11?的時候詳細討論他。
??小提示?在?API?中最好的做法是使用不同的模型作為?Request?和Response?實體。例如,實體?ID?一般僅僅是?Response?模型需要的,如果?Request?中需要的話,是可以從?URI?中拿到的。
?
代碼
??清單?1-19?展示了一個模型有多種驗證的情況:
RequiredAttribute,MaxLengthAttribute?和
RangeAttribute。接下來,我們就可以利用?ModelState?來驗證?Controller?中的驗證狀態,同時響應適當的提示信息給調用端。
清單 1-19. 簡單的 Web API 模型驗證
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public?class?Album { ????public?int?Id?{?get;?set;?} ????[Required(ErrorMessage?=?"{0} is?required")] ????[MaxLength(30)] ????public?string?Artist?{?get;?set;?} ????[Required(ErrorMessage?=?"{0} is?required")] ????[MaxLength(40)] ????public?string?Title?{?get;?set;?} ????[Range(0,?10,?ErrorMessage?=?"{0} in?the?range?of {1}-{2} is?required.")] ????public?int?Rating?{?get;?set;?} } public?class?AlbumController?:?ApiController { ????public?HttpResponseMessage?Post(Album?album) ????{ ????????if?(!ModelState.IsValid) ????????{ ????????????throw?new?HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, ????????????ModelState)); ????????} ????????//omitted?for?brevity ????} } |
?
?
??負責處理?ModelState?代碼的一般驗證可以很容易從?Controller?提取到成公共的部分,使其可以被很好的重用,不過這一部分我們將在?5-4?的時候再詳細介紹。
??現在,我們考慮一下這個場景,如果我們要在模型上增加增加兩個額外的屬性?Rating?和?Starred,同時擴展模型驗證,驗證的要求是這兩個屬性至少有一個是必填的。雖然,在兩個屬性之間糾纏的驗證很難使用聲明的方式來表示,但是,不要忘記?IValidateableObject?可以幫我們。我們可以使用接口中的?Validata?的方法去檢查整個模型的狀態,同時返回相應的?ValidationResult。我們要做的修改如清單?1-20?所示的代碼。
?
清單 1-20. 修改 ASP.NET Web API 依賴于 IValidateableObject 的驗證
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public?class?Album?:?IValidatableObject { ????public?int?Id?{?get;?set;?} ?? ????[Required(ErrorMessage?=?"{0} is?required")] ????[MaxLength(30)] ????public?string?Artist?{?get;?set;?} ?? ????[Required(ErrorMessage?=?"{0} is?required")] ????[MaxLength(40)] ????public?string?Title?{?get;?set;?} ?? ????public?int??Rating?{?get;?set;?} ????public?bool??Starred?{?get;?set;?} ?? ????public?IEnumerable<ValidationResult>?Validate(ValidationContext?validationContext) ????{ ????????if?(!(Rating.HasValue?&&?Rating?>?0?&&?Rating?<?10)?||?(Starred.HasValue?&&?Starred.Value)) ????????{ ????????????yield?return?new?ValidationResult("You?must?set?either?the?Rating?in?the?0-9?range?orStarred?flag."); ????????} ????} } |
轉載于:https://www.cnblogs.com/shuizhucode/p/6064260.html
總結
以上是生活随笔為你收集整理的[水煮 ASP.NET Web API2 方法论](1-6)Model Validation的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebDriver API元素的定位
- 下一篇: 课程2 谈论音乐行业的趋势