在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一. 模型绑定 ASP.NET Core MVC 中的模型绑定,是将 HTTP 请求中的数据映射到 action方法参数。 这些参数可能是简单类型的参数,如字符串、整数或浮点数,也可能是复杂类型的参数。 当 MVC 收到 HTTP 请求时,它会将此请求路由定位到控制器的指定 action方法。默认路由模板为 //例如:请求URL http://contoso.com/movies/edit/2 //映射到movies/edit/2 public IActionResult Edit(int? id) 上面Url请求对应movies控制器下的Edit方法,该方法接受名为 上面示例绑定的参数是简单类型,如果参数是一个类,例如 如果模型绑定失败,MVC 不会引发错误,参数值会是null。 如果HTTP 请求中的数据是用户输入的值,在action中应使用 注意:若要实现模型绑定,该类必须具有要绑定的公共默认构造函数和公共可写属性。 发生模型绑定时,在使用公共默认构造函数对类进行实例化后才可设置属性。 模型绑定完成后,将发生模型验证。 对于绝大多数开发方案,默认模型绑定效果极佳。还可以扩展,如果有特殊需求,则可自定义内置行为包括:模型绑定特性、全局自定义模型绑定和验证、绑定请求正文中的带格式数据(JSON、XML 和许多其他格式)、还有高级篇中自定义模型绑定。这里不在说明,请查看文档。 二.模型验证 在将数据存储到数据库之前,应用程序必须先验证数据。在 MVC 中,验证发生在客户端和服务器上。 2.1 验证属性 验证属性是模型验证的一种方法, 概念上类似于对数据库表中字段的验证, 验证属性在属性级别指定,下面是一个示例: 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 )。 所有的内置验证属性 参考官网 2.2 自定义验证 上面的验证属性适用于大多数验证需求。 但是,某些验证规则特定于你的业务。在 MVC 中创建自定义验证属性很简单。只需从 /// <summary> /// 自定义验证 /// </summary> public class ClassicMovieAttribute : ValidationAttribute { 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 年以后发行的电影的流派设置为 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 插件。客户端验证原理是: MVC 的标记帮助程序和 HTML 帮助程序则能够使用模型属性中的验证特性和类型元数据,呈现需要验证的表单元素中的 HTML 5 data- 属性。MVC 为内置模型属性和自定义模型属性生成 data- 属性。然后,jQuery 非介入式验证分析 下面示例表单中,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 输出中的 <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 动态表单添加验证 在创建动态表单后,需要立即对其进行分析。 例如,下面的代码展示如何对通过 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); } })
下面用一个简单示例来说明: (1) 创建dynamic-form-validate.js文件,模拟动态生成表单,以及点击(#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="动态加载表单" 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> } 运行程序,点击"动态加载表单" 调用js将html表单添加到form-container元素容器中,点击save提示该字段不能为空,效果如下所示: 2.5 动态控件添加验证 当向表单动态添加控件(比如: $.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) { //向表单动态添加Input控件 var form = document.getElementById("my-form"); form.insertAdjacentHTML("beforeend", newInputHTML); //移除现有的验证 $(form).removeData("validator") // Added by jQuery Validate .removeData("unobtrusiveValidation"); // Added by jQuery Unobtrusive Validation //重新分析整个表单 $.validator.unobtrusive.parse(form); } }) 2.6 IClientModelValidator 在上面2.2自定义验证中,继承了ValidationAttribute进行服务端验证,还可以结合实现IClientModelValidator接口实现客户端验证,该接口用来控制要添加哪些 data- 属性。实现接口如下所示: /// <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 年以后发行的电影的流派设置为 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"> 在上面虽然实现了IClientModelValidator接口,但jQuery不了解规则或消息,还需要自定义 //添加验证方法 $.validator.addMethod('classicmovie',function (value, element, params) { //value ,是当前验证的元素的值。 //element 元素本身。 //params 是传入的参数(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; }); //注册一个适配器,参数1是适配器名称,参数2是验证规则的名称 $.validator.unobtrusive.adapters.add('classicmovie',['year'],function (options) { //适配器规则绑定到jquery validation上面 options.rules['classicmovie'] = [parseInt(options.params['year'])]; options.messages['classicmovie'] = options.message; }); 运行程序,ReleaseDate是1989年,Genre是Classic,点击Save,客户端验证返回false,提示错误信息,如下所示: 参考文献 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持极客世界。 |
请发表评论