asp.net core系列之模型綁定和驗證方法
一. 模型綁定
ASP.NET Core MVC 中的模型綁定,是將 HTTP 請求中的數(shù)據(jù)映射到 action方法參數(shù)。 這些參數(shù)可能是簡單類型的參數(shù),如字符串、整數(shù)或浮點數(shù),也可能是復雜類型的參數(shù)。 當 MVC 收到 HTTP 請求時,它會將此請求路由定位到控制器的指定 action方法。默認路由模板為 {controller=Home}/{action=Index}/{id?}
//例如:請求URL http://contoso.com/movies/edit/2 //映射到movies/edit/2 public IActionResult Edit(int? id)
上面Url請求對應movies控制器下的Edit方法,該方法接受名為 id 的可選參數(shù)。MVC會將Edit中的id參數(shù)綁定到路由值中 具有相同名稱 的值。 URL 路由中的字符串不區(qū)分大小寫。
上面示例綁定的參數(shù)是簡單類型,如果參數(shù)是一個類,例如 Movie 類型,該類包含簡單和復雜類型作為屬性,MVC的模型綁定仍然可以很好地處理它。它使用反射和遞歸來遍歷尋找匹配的復雜類型的屬性(如:Collection、Dictionary)。
如果模型綁定失敗,MVC 不會引發(fā)錯誤,參數(shù)值會是null。 如果HTTP 請求中的數(shù)據(jù)是用戶輸入的值,在action中應使用 ModelState.IsValid 屬性檢查,不需要手動去檢查。
注意:若要實現(xiàn)模型綁定,該類必須具有要綁定的公共默認構造函數(shù)和公共可寫屬性。 發(fā)生模型綁定時,在使用公共默認構造函數(shù)對類進行實例化后才可設置屬性。
模型綁定完成后,將發(fā)生模型驗證。 對于絕大多數(shù)開發(fā)方案,默認模型綁定效果極佳。還可以擴展,如果有特殊需求,則可自定義內置行為包括:模型綁定特性、全局自定義模型綁定和驗證、綁定請求正文中的帶格式數(shù)據(jù)(JSON、XML 和許多其他格式)、還有高級篇中自定義模型綁定。這里不在說明,請查看文檔。
二.模型驗證
在將數(shù)據(jù)存儲到數(shù)據(jù)庫之前,應用程序必須先驗證數(shù)據(jù)。在 MVC 中,驗證發(fā)生在客戶端和服務器上。
2.1 驗證屬性
驗證屬性是模型驗證的一種方法, 概念上類似于對數(shù)據(jù)庫表中字段的驗證, 驗證屬性在屬性級別指定,下面是一個示例:
public class Movie
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Title { get; set; }
[ClassicMovie(1960)]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
[StringLength(1000)]
public string Description { get; set; }
[Range(0, 999.99)]
public decimal Price { get; set; }
[Required]
public Genre Genre { get; set; }
public bool Preorder { get; set; }
}
常用的內置驗證屬性包括: [ CreditCard] 信用卡格式、 [Compare]匹配兩個屬性、 [ EmailAddress] 郵件格式、 [ Phone] 電話格式、 [Range] 給定范圍內、 [RegularExpression] 正則表達式、 [Required]必須屬性值、 [StringLength] 最大長度、 [Url] URL格式,還可以包括自定義驗證屬性(例如 ClassicMovie )。 所有的內置驗證屬性 參考官網(wǎng)
2.2 自定義驗證
上面的驗證屬性適用于大多數(shù)驗證需求。 但是,某些驗證規(guī)則特定于你的業(yè)務。在 MVC 中創(chuàng)建自定義驗證屬性很簡單。只需從 ValidationAttribute 繼承并重寫 IsValid 方法。 IsValid 方法采用兩個參數(shù),第一個是名為 value 的對象,第二個是名為 validationContext 的 ValidationContext 對象。 Value 引用自定義驗證程序要驗證的字段中的實際值。
/// <summary>
/// 自定義驗證
/// </summary>
public class ClassicMovieAttribute : ValidationAttribute
{
private int _year;
/// <summary>
/// 驗證規(guī)則值
/// </summary>
/// <param name="year"></param>
public ClassicMovieAttribute(int year)
{
_year = year;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Movie movie = (Movie)validationContext.ObjectInstance;
//用戶不能將 1960 年以后發(fā)行的電影的流派設置為 Classic
if (movie.Genre == "Classic" && movie.ReleaseDate.Year > _year)
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
private string GetErrorMessage()
{
return $"Classic movies must have a release year earlier than {_year}.";
}
}
運行程序,ReleaseDate是1989年,Genre是Classic,點擊Save,驗證是在服務端進行,顯示錯誤消息,沒有經過前端js驗證,如下所示:

2.3 客戶端js驗證介紹
jQuery 非介入式驗證腳本是一個自定義微軟前端庫,建立在流行的 jQuery Validate 插件??蛻舳蓑炞C原理是: MVC 的標記幫助程序和 HTML 幫助程序則能夠使用模型屬性中的驗證特性和類型元數(shù)據(jù),呈現(xiàn)需要驗證的表單元素中的 HTML 5 data- 屬性。MVC 為內置模型屬性和自定義模型屬性生成 data- 屬性。然后,jQuery 非介入式驗證分析 data- 屬性并將邏輯傳遞給 jQuery Validate,從而將服務器端驗證邏輯有效地“復制”到客戶端。 可以使用相關標記幫助程序在客戶端上顯示驗證錯誤。
下面示例表單中,asp- 標記幫助程序代碼如下:
<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>
標記幫助程序將生成以下source html。請注意,HTML 輸出中的 data- 屬性與 ReleaseDate 屬性的驗證特性相對應。下面的 data-val-required 屬性包含在用戶未填寫發(fā)行日期字段時將顯示的錯誤消息。jQuery 非介入式驗證將此值傳遞給 jQuery Validate required() 方法,該方法隨后在隨附的 <span> 元素中顯示該錯誤消息。
<form action="/Movies/Create" method="post">
<div class="form-horizontal">
<h4>Movie</h4>
<div class="text-danger"></div>
<div class="form-group">
<label class="col-md-2 control-label" for="ReleaseDate">ReleaseDate</label>
<div class="col-md-10">
<input class="form-control" type="datetime"
data-val="true" data-val-required="The ReleaseDate field is required."
id="ReleaseDate" name="ReleaseDate" value="" />
<span class="text-danger field-validation-valid"
data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
</div>
</div>
</div>
</form>
2.4 動態(tài)表單添加驗證
在創(chuàng)建動態(tài)表單后,需要立即對其進行分析。 例如,下面的代碼展示如何對通過 AJAX 添加的表單設置客戶端驗證。
$.get({
url: "https://url/that/returns/a/form",
dataType: "html",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": Couldn't add form. " + errorThrown);
},
success: function(newFormHTML) {
//添加表單newFormHTML
var container = document.getElementById("form-container");
container.insertAdjacentHTML("beforeend", newFormHTML);
//驗證第一個表單
var forms = container.getElementsByTagName("form");
var newForm = forms[forms.length - 1];
//分析表單的 data- 屬性
$.validator.unobtrusive.parse(newForm);
}
})
$.validator.unobtrusive.parse() 方法分析該選擇器內表單的 data- 屬性。當用戶填寫表單中的屬性值提交時, 這些屬性的值傳遞到 jQuery Validate 插件中,以便表單展示所需的客戶端驗證規(guī)則。
下面用一個簡單示例來說明:
(1) 創(chuàng)建dynamic-form-validate.js文件,模擬動態(tài)生成表單,以及點擊(#idbtn)按鈕時驗證:
var newFormHTML = "<form action=\"create\" method=\"post\">";
newFormHTML += "<div class=\"form-group\">";
newFormHTML += "<label asp-for=\"Title\" class=\"control- label\"></label>";
newFormHTML += "<input type=\"text\" data-val=\"true\" data-val-required=\"The Title field is required.\" id = \"Title\" name= \"Title\">";
newFormHTML += "<span class=\"text- danger field- validation - valid\" data-valmsg-for=\"Title\" data-valmsg-replace=\"true\"></span>";
newFormHTML += "</div>";
newFormHTML += "<div class=\"form-group\" >";
newFormHTML += "<input type=\"submit\" value=\"Save\" class=\"btn btn-primary\" />";
newFormHTML += "</div >";
newFormHTML += "</form>";
$("#idbtn").click(function () {
var container = document.getElementById("form-container");
container.insertAdjacentHTML("beforeend", newFormHTML);
var forms = container.getElementsByTagName("form");
var newForm = forms[forms.length - 1];
//分析表單的 data- 屬性
$.validator.unobtrusive.parse(newForm);
});
(2) 新建create頁
@model StudyMVCDemo.Models.Movie
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<div class="row">
<input value="動態(tài)加載表單" type="button" id="idbtn" />
<div id="form-container" class="col-md-4">
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script src="~/js/dynamic-form-validate.js"></script>
}
運行程序,點擊"動態(tài)加載表單" 調用js將html表單添加到form-container元素容器中,點擊save提示該字段不能為空,效果如下所示:

2.5 動態(tài)控件添加驗證
當向表單動態(tài)添加控件(比如: <input/> 和 <select/> )時,需要更新表單上的驗證規(guī)則。做法是應當先刪除現(xiàn)有的驗證數(shù)據(jù),然后重新分析整個表單,如下js代碼所示:
$.get({
url: "https://url/that/returns/a/control",
dataType: "html",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": Couldn't add control. " + errorThrown);
},
success: function(newInputHTML) {
//向表單動態(tài)添加Input控件
var form = document.getElementById("my-form");
form.insertAdjacentHTML("beforeend", newInputHTML);
//移除現(xiàn)有的驗證
$(form).removeData("validator") // Added by jQuery Validate
.removeData("unobtrusiveValidation"); // Added by jQuery Unobtrusive Validation
//重新分析整個表單
$.validator.unobtrusive.parse(form);
}
})
2.6 IClientModelValidator
在上面2.2自定義驗證中,繼承了ValidationAttribute進行服務端驗證,還可以結合實現(xiàn)IClientModelValidator接口實現(xiàn)客戶端驗證,該接口用來控制要添加哪些 data- 屬性。實現(xiàn)接口如下所示:
/// <summary>
/// 自定義驗證
/// </summary>
public class ClassicMovieAttribute : ValidationAttribute,IClientModelValidator
{
private int _year;
/// <summary>
/// 年份參考值
/// </summary>
/// <param name="year"></param>
public ClassicMovieAttribute(int year)
{
_year = year;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Movie movie = (Movie)validationContext.ObjectInstance;
//用戶不能將 1960 年以后發(fā)行的電影的流派設置為 Classic
if (movie.Genre == "Classic" && movie.ReleaseDate.Year > _year)
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
private string GetErrorMessage()
{
return $"Classic movies must have a release year earlier than {_year}.";
}
public void AddValidation(ClientModelValidationContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-classicmovie", GetErrorMessage());
var year = _year.ToString(CultureInfo.InvariantCulture);
MergeAttribute(context.Attributes, "data-val-classicmovie-year", year);
}
private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}
}
生成的源html代碼如下所示:
<input class="form-control" type="date" data-val="true" data-val-classicmovie="Classic movies must have a release year earlier than 1960." data-val-classicmovie-year="1960" data-val-required="The ReleaseDate field is required." id="ReleaseDate" name="ReleaseDate" value="1989-02-12">
在上面雖然實現(xiàn)了IClientModelValidator接口,但jQuery不了解規(guī)則或消息,還需要自定義 classicmovie 客戶端驗證方法,添加到jQuery validator 對象。腳本如下所示:
//添加驗證方法
$.validator.addMethod('classicmovie',function (value, element, params) {
//value ,是當前驗證的元素的值。
//element 元素本身。
//params 是傳入的參數(shù)(options.rules)
var genre = $("#form1").find("#Genre").val(),
year = params[0],
date = new Date(value);
if (genre.length > 0 && genre === 'Classic') {
// Since this is a classic movie, invalid if release date is after given year.
return date.getFullYear() <= year;
}
return true;
});
//注冊一個適配器,參數(shù)1是適配器名稱,參數(shù)2是驗證規(guī)則的名稱
$.validator.unobtrusive.adapters.add('classicmovie',['year'],function (options) {
//適配器規(guī)則綁定到jquery validation上面
options.rules['classicmovie'] = [parseInt(options.params['year'])];
options.messages['classicmovie'] = options.message;
});
運行程序,ReleaseDate是1989年,Genre是Classic,點擊Save,客戶端驗證返回false,提示錯誤信息,如下所示:

參考文獻
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- ASP.NET?Core?模型驗證消息的本地化新姿勢詳解
- ASP.NET?Core?6.0?基于模型驗證的數(shù)據(jù)驗證功能
- ASP.NET?Core中Cookie驗證身份用法詳解
- asp.net core3.1cookie和jwt混合認證授權實現(xiàn)多種身份驗證方案
- asp.net core配合vue實現(xiàn)后端驗證碼邏輯
- [Asp.Net Core]用Blazor Server Side實現(xiàn)圖片驗證碼
- ASP.NET Core實現(xiàn)自定義WebApi模型驗證詳解
- ASP.NET Core WebApi中使用FluentValidation驗證數(shù)據(jù)模型的方法
相關文章
MVC使用Controller代替Filter完成登錄驗證(Session校驗)學習筆記5
這篇文章主要介紹了MVC使用Controller代替Filter完成登錄驗證即Session校驗,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09
ASP.NET MVC 開發(fā)微信支付H5的實現(xiàn)示例(外置瀏覽器支付)
這篇文章主要介紹了ASP.NET MVC 開發(fā)微信支付H5的實現(xiàn)示例(外置瀏覽器支付),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-12-12
VS2015在升級到Update2之后運行Cordova項目異常的解決方案
這篇文章主要介紹了VS2015在升級到Update2之后運行Cordova項目異常的解決方案的相關資料,需要的朋友可以參考下2016-07-07
靜態(tài)gb2312編碼在項目傳值出現(xiàn)中文亂碼現(xiàn)象
參考的美工靜態(tài)頁面是gb2312格式的,當此編碼拿到項目中后,utf-8編碼的系統(tǒng),加載頁面時,會出現(xiàn)樣式問題,比如不能正常居中等2013-06-06
ASP.NET?Core?實現(xiàn)自動刷新JWT?Token
這篇文章主要介紹了ASP.NET?Core?實現(xiàn)自動刷新JWT?Token,通過增加??refresh_token??,客戶端使用refresh_token去主動刷新JWT?Token,下文具體操作過程需要的小伙伴可以參考一下2022-04-04

