标签:function bag 接口 特性 请求 mamicode case component reg
Asp.Net MVC在针对目标Aciton方法的某个参数实施绑定过程中会将ValueProvider提供的数据保存在当前Controller的ModelState中。具体来说,Controller的ModelState是其ViewData的一部分,它返回一个ModelStateDictionary对象,我们通常通过其IsValid方法判断是否包含的所有ModelState均有效,即请求提交的数据是否均通过验证。
很多情况下,我们以表单的方式向服务端提交数据,如果针对参数的验证失败,相同的页面一般会再次呈现出来。那么我们在View呈现的时候如何显示验证错误消息呢?
通常我们调用帮助类HtmlHelper和HtmlHelper<TModel>定义的扩展方法ValidationMessage和ValidationMessageFor和ValidationSummary来实现针对验证错误的呈现,我们先来看以下代码
public class User { public int Id { get; set; }
[DisplayName("姓名")] [Required(ErrorMessage = "用户名不能为空")] public string UserName { get; set; }
[DisplayName("密码")] [Required(ErrorMessage ="密码不能为空")] [MinLength(6,ErrorMessage = "密码长度必须大于6位")] public string PassWord { get; set; } [EmailAddress] public string Email { get; set; } [Phone] public string Phone { get; set; } }
@model WebApplication2.Models.User @{ ViewBag.Title = "Register"; } <br /> <br /> <br /> <form method="post" action="Register"> @Html.ValidationSummary() <div> @Html.LabelFor(u=>u.UserName) @Html.TextBox("UserName") @Html.ValidationMessageFor(u => u.UserName) </div> <div> @Html.LabelFor(u=>u.PassWord) @Html.TextBox("PassWord") @Html.ValidationMessageFor(u => u.PassWord) </div> <div> @Html.Label("邮箱") @Html.TextBox("Email") @Html.ValidationMessageFor(u => u.Email) </div> <div> @Html.Label("手机号码") @Html.TextBox("Phone") @Html.ValidationMessageFor(u => u.Phone) </div> <input type="submit" value="提交" /> </form>
除了使用特性验证,我们可以手动验证绑定的参数,验证不通过时可以使用下面的方式将错误信息放入ModelState中。
ModelState.AddModelError("UserName", "用户名不能为空");
但是不管怎么说,将输入参数的验证逻辑和业务逻辑定义在Action中并不是一种值得推荐的编程方式。而这也是Asp.Net MVC的Model验证系统默认支持的变成方式。命名空间 System.ComponentModel.DataAnnotations 定义了一系列具体的ValidationAttribute特性类型,常规的验证可以通过这些预定义的特性来完成,但是很多情况下我们需要通过创建自定义的ValidationAttribute特性来解决一些特殊的验证。那我们应该怎么做呢?
我们可以定义一个继承ValidateAttribute的特性类来实现自定义的验证特性。下面我们针对“某个值必须在指定的范围内”这样的验证规则来定义我们自己的特性。
/// <summary> /// 判断某个值是否在指定的范围内 /// </summary> [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,AllowMultiple = false)] public class DomainAttribute : ValidationAttribute { public IEnumerable<string> Values { get; private set; } public DomainAttribute(params string[] values) { this.Values = values; } public override bool IsValid(object value) { if (null == value) { return true; } return this.Values.Any(item => value.ToString() == item); } public override string FormatErrorMessage(string name) { string[] values = this.Values.Select(v => string.Format("‘{0}‘", v)).ToArray(); return string.Format(base.ErrorMessageString, name, string.Join(",", values)); } }
public class User { public int Id { get; set; } [DisplayName("姓名")] [Required(ErrorMessage = "用户名不能为空")] public string UserName { get; set; } [DisplayName("密码")] [Required(ErrorMessage ="密码不能为空")] [MinLength(6,ErrorMessage = "密码长度必须大于6位")] public string PassWord { get; set; } [EmailAddress] public string Email { get; set; } [Domain("male","female")] public string Gender { get; set; } [Phone] public string Phone { get; set; } }
实际上除了将验证规则通过ValidationAttribute特性直接定义在数据类型上,还可以让数据类型实现 IValidationObject 接口 或 IDataErroInfo接口,具体可以看下main代码:
public class User: IValidatableObject { public string Name { get; set; } public string Gender { get; set; } public int Age { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { User user = validationContext.ObjectInstance as User; if(null == user) { yield break; } if (string.IsNullOrEmpty(user.Name)) { yield return new ValidationResult("Name是必须字段", new string[] { "Name" }); } if(!new string[] { "M","F"}.Any(g=>string.Compare(user.Gender,g,true) == 0)){ yield return new ValidationResult("Gender的有效值必须是‘M‘或‘F‘", new string[] { "Gender" }); } } }
public class User : IDataErrorInfo { public string this[string columnName] { get { switch (columnName) { case "Name": if (string.IsNullOrEmpty(this.Name)) { return "姓名不能为空"; } return null; case "Gender": if (!new string[] { "M", "F" }.Any(g => string.Compare(this.Gender, g, true) == 0)) { return "Gender的有效值必须是‘M‘或‘F‘"; } return null; default: return null; } } } public string Name { get; set; } public string Gender { get; set; } public int Age { get; set; } [ScaffoldColumn(false)] public string Error { get; private set; } }
最后,我们前面讲的都是在服务端做的验证,那么我们可不可以在客户端的时候就做一些必要的验证呢,答案当然是肯定的。
<script src="~/Scripts/jquery-3.3.1.min.js"></script> <script src="~/Scripts/jquery.validate.min.js"></script> <script> $(function () { $("form").validate({ rules: { name: { required: true }, birthDate: { required: true, date: true }, email: { required: true, email: true } }, messages: { name: { required: "请输入姓名" }, birthDate: { required: "请输入出生日期", date:"请输入合法日期" }, email: { required: "请输入Email地址", email:"请输入合法的Email地址" } } }); }) </script>
如果需要结合ValidateAttribute特性来做客户端验证的话,我们可以这么做,多引入一个.js文件
@model WebApplication2.Models.User @{ ViewBag.Title = "Register"; } <script src="~/Scripts/jquery-3.3.1.min.js"></script> <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> @using (Html.BeginForm()) { @Html.EditorForModel() <input type="submit" value="提交" /> }
public class User { public int Id { get; set; } [DisplayName("姓名")] [Required(ErrorMessage = "用户名不能为空")] public string UserName { get; set; } [DisplayName("密码")] [Required(ErrorMessage ="密码不能为空")] [MinLength(6,ErrorMessage = "密码长度必须大于6位")] public string PassWord { get; set; } [EmailAddress] public string Email { get; set; } [Domain("M","F")] public string Gender { get; set; } [Phone] public string Phone { get; set; } } /// <summary> /// 判断某个值是否在指定的范围内 /// </summary> [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,AllowMultiple = false)] public class DomainAttribute : ValidationAttribute { public IEnumerable<string> Values { get; private set; } public DomainAttribute(params string[] values) { this.Values = values; } public override bool IsValid(object value) { if (null == value) { return true; } return this.Values.Any(item => value.ToString() == item); } public override string FormatErrorMessage(string name) { string[] values = this.Values.Select(v => string.Format("‘{0}‘", v)).ToArray(); return string.Format(base.ErrorMessageString, name, string.Join(",", values)); } }
标签:function bag 接口 特性 请求 mamicode case component reg
原文地址:https://www.cnblogs.com/jesen1315/p/11017532.html