網(wǎng)站首頁 編程語言 正文
1.模型綁定
ASP.NET Core MVC 中的模型綁定將數(shù)據(jù)從HTTP請求映射到操作方法參數(shù)。參數(shù)既可以是簡單類型,也可以是復(fù)雜類型。MVC 通過抽象綁定解決了這個問題。
2.使用模型綁定
當(dāng) MVC 收到一個HTTP 請求時,它會將其路由到一個控制器指定的操作方法。它基于路由數(shù)據(jù)來決定運行哪個操作,然后將值從HTTP請求綁定到操作方法的參數(shù)中,例如
http://afei.com/movies/edit/2
movies/edit/2 通過路由模板路由到 Movies 控制器的 Edit 方法,同時接收到一個可選參數(shù) id 。URL 中的字符串是不區(qū)分大小寫的。
MVC 將嘗試通過名稱將請求數(shù)據(jù)綁定到操作參數(shù)上。 MVC 將使用參數(shù)名稱和其公共可設(shè)置的屬性名稱查找每個參數(shù)值。上面的例子,唯一的操作參數(shù)被命名為 id ,其中 MVC 綁定到路由值中具有相同名稱的值。除了 路由值, MVC 還綁定請求的各個部分的數(shù)據(jù),并按照設(shè)置的順序這樣做。
模型綁定查找數(shù)據(jù)源的順序列表:
- 1. Form values : 通過 HTTP POST 請求發(fā)送的表單數(shù)據(jù)(包括 jQuery POST 請求)。
- 2. Route values :由 routing 提供的路由數(shù)據(jù)集。
- 3. Query string : URL 的查詢字符串的一部分。
表單值,路由數(shù)據(jù)以及查詢字符串都是以鍵值對的形式存儲的。
因為模型綁定要找一個名為 id 的鍵,但是表單中沒有,所以接下來在路由數(shù)據(jù)中找尋。綁定發(fā)生時,該值轉(zhuǎn)換為整數(shù)類型的 2 。使用 Edit(string id)的同一請求轉(zhuǎn)換為字符串 “2” .
如果Action 方法的參數(shù)是一個類,比如 Movies 類型,盡管這個類包含簡單類型和復(fù)雜類型的屬性,MVC 也可以模型綁定。它使用反射和遞歸遍歷復(fù)雜類型尋找匹配的屬性。模型綁定尋找 parameter_name.property_name 的模式去綁定值到屬性上。如果沒有從表單中找到匹配的值,則嘗試只通過?property_name? 進行綁定。對于集合類型,模型綁定會去匹配?parameter_name[index] 或只是 [index] 。模型綁定對待字典類型也是一樣,前提是Key 是簡單類型。Key 支持匹配HTML 和 Tag Helpers 為相同的模型類型生成的字段名。當(dāng)創(chuàng)建或編輯的綁定數(shù)據(jù)未通過驗證時,回傳值使得用戶輸入的表單字段仍然保留,方便用戶輸入。
為了發(fā)生綁定,類必須具有公共默認(rèn)的構(gòu)造函數(shù),要綁定的成員必須是公共可寫的屬性,當(dāng)綁定發(fā)生時,類只會使用公共默認(rèn)的構(gòu)造函數(shù),然后設(shè)置屬性。
當(dāng)一個參數(shù)被綁定后,模型綁定停止尋找具有該名稱的值,并繼續(xù)綁定下一個參數(shù)。如果綁定失敗,MVC? 也不會拋出異常,可以通過ModelState.IsValid 屬性來查詢模型狀態(tài)錯誤。
在執(zhí)行綁定時,需要考慮一些特殊的數(shù)據(jù)類型:
- IFormFile , IEnumerable<IFormFile> :作為 HTTP 請求一部分的一個或多個上傳的文件。
- CancelationToken : 用于取消一部控制器中的活動。
這些類型可以綁定到操作參數(shù)或類的屬性上。
一旦模型綁定完成,就會進行驗證。默認(rèn)模型綁定適合絕大多數(shù)開發(fā)場景,同時也可以自定義內(nèi)置的行為。
3.通過特性自定義模型綁定行為
MVC 包含集中可以指定與默認(rèn)綁定源不同行為的特性。比如,可以通過使用 [BindRequired] 或 [BindNever] 特性指定一個屬性是否需要綁定,或者是否該發(fā)生。而且可以覆蓋默認(rèn)數(shù)據(jù)源,指定模型綁定器的數(shù)據(jù)源。
- [BindRequired] :如果不發(fā)生綁定,將添加模型狀態(tài)錯誤。
- [BingNever] : 告訴模型綁定從不綁定到此參數(shù)。
- [FromHeader] , [FromQuery] , [FromRoute] , [FromForm] : 使用這些來指定應(yīng)用的確切綁定源。
- [FromServices] : 此特性使用依賴注入來綁定服務(wù)的參數(shù)。
- [FromBody] : 使用配置的格式化程序綁定請求主體中的數(shù)據(jù),基于請求的內(nèi)容類型選擇格式化器。
- [ModelBinder] : 用于覆蓋默認(rèn)模型綁定器,綁定源和名稱。
4.從請求主體綁定格式化的數(shù)據(jù)
HTTP 請求數(shù)據(jù)支持各種的格式,包括 JSON , XML 以及其他格式。當(dāng)使用 [FromBody] 特性的時候,表示要從請求主體中綁定參數(shù)。MVC 使用一組配置的格式化程序來根據(jù)其內(nèi)容類型處理請求數(shù)據(jù)。默認(rèn)情況下,MVC 包含一個 JsonInputFormatter 類來處理JSON數(shù)據(jù),當(dāng)然也可以添加其他格式化程序來處理XML 和其他自定義格式。
每個操作最多可以有一個 [Frombody] 裝飾的參數(shù)。ASP.NET Core MVC 運行時將讀取請求流的職責(zé)委托給格式化程序。一旦讀取了參數(shù)的請求流,通常不可能再次讀取請求流以綁定其他 [FromBody] 參數(shù)。
ASP.NET 基于Content-Type 頭和參數(shù)的類型來選擇輸入格式化程序。如果想用 XML 或者其他格式,則必須在 Startup.cs 文件中配置它,但首先使用 NuGet 來獲取 Microsoft.AspNetCore.Mvc.Formatters.Xml 引用。啟動代碼如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddXmlSerializerFormatters();
}
示例中,我們添加一個XML 格式化程序作為此MVC應(yīng)用程序提供的服務(wù)。傳遞給?AddMvc 方法的 options參數(shù)允許在應(yīng)用程序啟動時從MVC添加和管理過濾器,格式化程序和其他系統(tǒng)選項,然后應(yīng)用各種特性到控制器類或方法上實現(xiàn)預(yù)期的效果。
5.模型驗證
在應(yīng)用程序?qū)?shù)據(jù)存儲到數(shù)據(jù)庫之前,應(yīng)用程序必須驗證數(shù)據(jù)。對于數(shù)據(jù)必須檢查其是否存在潛在的安全隱患,驗證類型和大小是否正確并且符合所定制的規(guī)則。盡管驗證的實現(xiàn)可能時冗余且繁瑣的,但是必要的。在 MVC 中,驗證可以發(fā)生在客戶端和服務(wù)端。
.NET 已經(jīng)將驗證抽象為驗證特性。這些特性包含驗證代碼,從而減少必須編碼。
public class Movies
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Title { get; set; }
[Required]
[ClassicMovie(1996)]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
[StringLength(100)]
public string Description { get; set; }
[Required]
[Range(0,999.99)]
public decimal Price { get; set; }
[Required]
public Genre Genre { get; set; }
public bool Preorder { get; set; }
}
常見內(nèi)置驗證屬性:
- [CreditCard] : 驗證屬性是否為信用卡格式
- [Compare] : 驗證模型中的兩個屬性是否匹配
- [EmailAddress] : 驗證屬性是否為電子郵件格式
- [Phone] : 驗證屬性是否為電話號碼格式
- [Range] : 驗證屬性值是否在給定范圍內(nèi)
- [RegularExpression] : 驗證數(shù)據(jù)是否與指定的正則表達式匹配
- [Required] : 必填的屬性
- [StringLength] : 驗證字符串屬性的最大長度
- [Url] : 驗證屬性是否為網(wǎng)址格式
MVC 支持從 ValidationAttribute 派生的任何特性或者更改模型來實現(xiàn) IAlidatableObject 即創(chuàng)建自定義驗證特性以用于驗證目的。許多內(nèi)置的驗證特性可以在?ystem.ComponentModel.DataAnnotations 中找到。
有時候我們需要手動需要驗證模型,可以調(diào)用 TryValidateModel 方法來驗證,如?TryValidateModel (movie)。
模型狀態(tài)表示在HTML表單提交值的一系列驗證錯誤。MVC 將持續(xù)驗證字段直到錯誤數(shù)達到最大值(默認(rèn)200)。可以在?ConfigureServices 方法中配置這個最大值:
services.AddMvc(options => options.MaxModelValidationErrors = 500);
模型驗證發(fā)生在每個控制器的操作 被調(diào)用之前,而檢查 ModelState.IsValid 和做出適當(dāng)?shù)姆磻?yīng)時操作方法的職責(zé)。許多情況下,適當(dāng)?shù)姆磻?yīng)是返回某種錯誤響應(yīng),理想情況下則是詳細(xì)介紹模型驗證失敗的原因。
6.自定義驗證
實現(xiàn)自定義驗證的方法很簡單,只需要繼承 ValidationAttribute,并且重寫 IsValid 方法即可。IsValid 方法接受兩個參數(shù),第一個是名為 value 的 object 對象,第二個對象是名為validationContext 的 ValidationContext 對象。value 指的是自定義驗證器驗證的字段的值。
下面自定義[ClassicMovie] 特性,該特性檢查 Movies 類的 ReleaseDate 年份是否大于1960:
public class ClassicMovieAttribute:ValidationAttribute
{
private int _year;
public ClassicMovieAttribute(int Year)
{
_year = Year;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Movies movie = (Movies)validationContext.ObjectInstance;
if (movie.ReleaseDate.Year > _year)
{
return new ValidationResult("發(fā)布年份不能大于"+_year);
}
return ValidationResult.Success;
}
}
這個例子只對 Movies 類型有效,因為在?IsValid 方法中硬編碼了??Movies 類型。一個更好的選擇是 IValidationObject。
通過在?IValidatableObject?接口上實現(xiàn) Validate 方法,可以將相同的代碼放在模型中。雖然自定義驗證屬性是用于驗證單個屬性,但實現(xiàn)?IValidationObject 可用于實現(xiàn)類級別驗證;
public class Movies: IValidatableObject
{
private int _classicYear = 1960;
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Title { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
[StringLength(100)]
public string Description { get; set; }
[Required]
[Range(0,999.99)]
public decimal Price { get; set; }
public bool Preorder { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (ReleaseDate.Year > _classicYear)
{
yield return new ValidationResult("發(fā)布年份不能大于" + _classicYear,new[] { "ReleaseDate" });
}
}
}
7.客戶端驗證
客戶端驗證帶來了極大便利,它可以節(jié)省時間,不必花費一個來回時間等待服務(wù)器的驗證結(jié)果。
你必須引用 Javascript 腳本來進行客戶端驗證;
jquery-x.x.x.min.js? ??jquery.validate.min.js? ? ?jquery.validate.unobtrusive.min.js
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.9/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha384-ifv0TYDWxBHzvAk2Z0n8R434FL1Rlv/Av18DXE43N/1rvHyOG4izKst0f2iSLdds">
</script>
除了模型屬性的類型元數(shù)據(jù)外,MVC 還用 Attribute 通過 Javascript 驗證數(shù)據(jù)并展示所有錯誤信息。當(dāng)使用 MVC 去渲染使用 Tag Helper 或者 HTML Helpers 的表單數(shù)據(jù)時,它將在需要驗證的表單元素中添加HTML? 5? data- attributes ,如下面,MVC 對內(nèi)置驗證 Attribute 和自定義驗證 Attribute 生成 data - 特性。可以通過?Tag Helper 在客戶端顯示驗證錯誤:
<div class="form-group">
<label asp-for="Id" class="control-label"></label>
<input asp-for="Id" class="form-control" />
<span asp-validation-for="Id" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseDate" class="control-label"></label>
<input asp-for="ReleaseDate" class="form-control" />
<span asp-validation-for="ReleaseDate" class="text-danger"></span>
</div>
上面的?Tag Helper? 渲染的 HTML 如下,注意輸出的 HTML 中,data-特性對應(yīng) Name 屬性的驗證 Attribute ,data-val-required?特性包含一個用于展示錯誤消息,如果沒填寫 ReleaseDate 字段,則錯誤消息將隨著<span>? 一起顯示:
<div class="form-group">
<label class="control-label" for="Id">Id</label>
<input name="Id" class="form-control" id="Id" type="number" value="" data-val-required="The Id field is required." data-val="true">
<span class="text-danger field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Id"></span>
</div>
<div class="form-group">
<label class="control-label" for="ReleaseDate">ReleaseDate</label>
<input name="ReleaseDate" class="form-control" id="ReleaseDate" data-val-required="The ReleaseDate field is required." data-val="true"
type="text" value=""> <span class="text-danger field-validation-valid" data-valmsg-replace="true" data-valmsg-for="ReleaseDate"></span> </div>
客戶端驗證防止表單提交直到有效為止。無論提交表單還是顯示錯誤信息,提交按鈕都會執(zhí)行 Javascript 代碼。
MVC 基于 .NET 屬性的數(shù)據(jù)類型決定了類型特性值。可以使用 [DataType] 特性來覆蓋。基礎(chǔ)的??[DataType]? 特性并不是真正的服務(wù)端驗證。瀏覽器選擇自己的錯誤信息,并顯示,但 Jquery Validation Unobtrusive 包可以重寫消息,并讓他們顯示方式一致。
8.遠程驗證
當(dāng)需要在客戶端上使用服務(wù)器上的數(shù)據(jù)進行驗證的時候,遠程驗證是一個很好的功能。比如,應(yīng)用程序需要驗證一個用戶名是否已經(jīng)被使用,并且需要查詢大量數(shù)據(jù)才能執(zhí)行。下載大量數(shù)據(jù)驗證會占用大量資源,也可能暴露敏感信息。另一個辦法是使用回傳請求來驗證。
兩個步驟就可以實現(xiàn)遠程驗證,首先必須使用 [Remote] 特性注釋模型屬性。?[Remote] 特性接受多個重載,可以使用它將客戶端 Javascript 定向到要調(diào)用的相應(yīng)代碼。下面的代碼時執(zhí)行 Users 控制器的 VerfyUser 方法:
public class User
{
[Remote(action: "VerfyUser",controller:"Users")]
public string Name { get; set; }
}
然后在?VerfyUser 方法中實現(xiàn)方法,它返回一個?JsonResult :
public class UsersController : Controller
{
public IActionResult VerfyUser(string name)
{
if (!_usersRepository.VerfyUser(name))
{
return Json(data:$"{name} 已存在");
}
return Json(data:true);
}
}
現(xiàn)在,當(dāng)用戶輸入名字時,視圖中的 JavaScript 會進行遠程調(diào)用進行驗證。
原文鏈接:https://www.cnblogs.com/afei-24/p/11183228.html
相關(guān)推薦
- 2022-06-28 ES6基礎(chǔ)語法之字符串?dāng)U展_基礎(chǔ)知識
- 2022-12-23 kotlin延遲初始化和密封類詳細(xì)講解_Android
- 2022-01-20 空值判斷運算符 ? ?
- 2023-04-18 Python設(shè)計模式中的策略模式詳解_python
- 2022-05-11 生產(chǎn)事故記錄(tomcat線程池與數(shù)據(jù)庫連接池)與(堆棧信息)Jprofile的使用
- 2022-04-09 如何利用python提取字符串中的數(shù)字_python
- 2023-03-25 Pandas庫中iloc[]函數(shù)的使用方法_python
- 2022-08-17 WPF中的導(dǎo)航框架概述_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支