.NET MVC 学习笔记(五)—— Data Validationcss
在实际应用中,咱们须要对数据进行增查改删业务,在添加和修改过程当中,不管你编写什么样的网页程序,都须要对用户的数据进行验证,以确数据的有效性和完整性。目前咱们可使用Bootstrap Validation对画面进行前端验证,咱们先来看一下这种验证方式。html
1、Bootstrap Validation前端
使用方式:jquery
1. 引用js库web
<link href="~/bower_components/bootstrap-validation/css/bootstrapValidator.min.css" rel="stylesheet" />ajax
<script src="~/bower_components/bootstrap-validation/js/bootstrapValidator.min.js"></script>正则表达式
2. 在页面中对validation进行初始化json
<div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> <h4 class="modal-title" id="myModalLabel"> 新增 </h4> </div> <div class="modal-body"> <div class="row clearfix"> @using (Html.BeginForm("Save", "Client", FormMethod.Post, new { @id = "frmClient" })) { <div class="form-group"> @Html.Hidden("Id") <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="CardNo" class="control-label">卡号 <span style="color:red">*</span></label> </div> <div class="col-sm-8"> <input type="text" class="form-control" name="CardNo" id="CardNo"> </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="UserName" class="control-label">会员名 <span style="color:red">*</span></label> </div> <div class="col-sm-8"> <input type="text" class="form-control" autocomplete="off" name="UserName" id="UserName"> </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="Sex" class="control-label">性别 <span style="color:red">*</span></label> </div> <div class="col-sm-8"> @Html.DropDownListFor(model => model.Sex, ViewBag.GenderList as IEnumerable<SelectListItem>, new { @class = "form-control textbox input-sm" }) </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="BirthdateText" class="control-label">出生日期 <span style="color:red">*</span></label> </div> <div class="col-sm-8"> <div class="input-group date"> <div class="input-group-addon"> <i class="fa fa-calendar"></i> </div> @Html.TextBoxFor(model => model.BirthdateText, new { @class = "form-control datepicker", @type = "text", @autocomplete = "off" }) </div> </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="Phone" class="control-label">手机号 <span style="color:red">*</span></label> </div> <div class="col-sm-8"> <input type="text" id="Phone" name="Phone" autocomplete="off" class="form-control input-sm span3"> </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="Address" class="control-label">地址</label> </div> <div class="col-sm-8"> <input type="text" id="Address" name="Address" autocomplete="off" class="form-control input-sm span3"> </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="Score" class="control-label">积分</label> </div> <div class="col-sm-8"> <input type="text" id="Score" name="Score" autocomplete="off" class="form-control input-sm span3"> </div> </div> <div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="GradeCode" class="control-label">等级</label> </div> <div class="col-sm-8"> @Html.DropDownListFor(model => model.GradeCode, ViewBag.GradeList as IEnumerable<SelectListItem>, new { @class = "form-control textbox input-sm" }) </div> </div> </div> } </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> 关闭 </button> <button type="button" class="btn btn-primary" id="btnSaveClient"> 保存 </button> </div> </div>
$('#frm').bootstrapValidator({ message: 'This value is not valid', feedbackIcons: { valid: 'glyphicon glyphicon-ok', invalid: 'glyphicon glyphicon-remove', validating: 'glyphicon glyphicon-refresh' }, fields: { CardNo: { verbose: false, validators: { notEmpty: { message: '卡号不能为空' }, remote: { type: 'POST', url: '@Url.Content("~/Client/CheckCardNo")', dataType: 'json', data: { ClientId: function () { return $('#Id').val() }, CardNo: function () { return $('#CardNo').val() } }, message: '此卡号已存在', delay: 200 } } }, UserName: { validators: { notEmpty: { message: '会员名不能为空' } } }, Phone: { validators: { notEmpty: { message: '手机号码不能为空' }, regexp: { regexp: /^1[3|5|8]{1}[0-9]{9}$/, message: '请输入正确的手机号码' } } }, Score: { validators: { regexp: { regexp: /^[\d]+$/, message: '积分必须为数字' } } } } });
如上代码所示,对frm表单进行验证初始化,CardNo,UserName等为控件的name属性bootstrap
运行效果以下:后端
其中,对CardNo有重复性check,此时须要使用remote进行验证,后台代码以下:
/// <summary> /// 检查CardNo /// </summary> /// <param name="ClientId"></param> /// <param name="CardNo"></param> /// <returns></returns> public JsonResult CheckCardNo(String ClientId, String CardNo) { try { // 检索条件 ClientFilter filter = new ClientFilter(); filter.CardNo = CardNo; List<ClientDomain> clients = ClientBiz.GetDomainByExactFilter(filter) as List<ClientDomain>; ValidaResult resObj = new ValidaResult(); resObj.valid = true; if (String.IsNullOrEmpty(ClientId) && clients.Count > 0) { resObj.valid = false; } else if (!String.IsNullOrEmpty(ClientId)) { if (clients.Count > 1) { resObj.valid = false; } else if (clients.Count == 1 && !clients[0].Id.Equals(ClientId)) { resObj.valid = false; } } return Json(resObj, JsonRequestBehavior.AllowGet); } catch (Exception ex) { Log.SaveException(ex); return new JsonResult() { JsonRequestBehavior = JsonRequestBehavior.AllowGet, Data = new { ResultTitle = Constant.Result_Title_Error, ResultMessage = ex.Message } }; } }
/// <summary> /// Valid 结果 /// </summary> [Serializable] [DataContract] public class ValidaResult { [DataMember] public Boolean valid { get; set; } }
验证效果以下:
regexp:是对字段进行正则表达式验证,能够根据本身的须要进行相应的验证。
还有密码确认密码验证
//密码确认 edit_passwd1: { message: '密码确认验证失败', validators: { notEmpty: { message: '密码确认不能为空' }, identical: { field: 'edit_passwd', message: '两次密码不相同' } } }
长度验证
stringLength: { min: 5, max: 128, message: '显示名长度必须在6到18位之间' }
等等
在提交画面变动时,须要进行验证
//开启验证 $('#frm').data('bootstrapValidator').validate(); if ($('#frm').bootstrapValidator('validate').has('.has-error').length != 0) { return; }
或者
var flag = $("#frm").data(“bootstrapValidator”).isValid();
验证经过以后进行页面数据提交
在画面初始化的时候,若是上次画面关闭前有验证消息,再次打开或许会出现验证消息依然存在的状况,这时候须要重置全部验证
$("frm").data("bootstrapValidator").resetForm();
以上,就是相关前端验证的内容。
========================================================================
是否是到这里就结束了,一开始我也觉得是的,源自于我对用户的信任,但是事实上大部分用户也彻底值得咱们的信任,可是做为开发者,咱们不能容许有异常发生。
以此为例:
请看下面的画面
这是对【会员名】的验证
UserName: { validators: { notEmpty: { message: '会员名不能为空' } } }
当咱们修改会员名,设置为空时
看起来一切正常,只有输入会员名咱们才能提交,可是当咱们输入会员名,并点击【保存】
咱们这时选择在代码中打入断点
此时咱们看到,代码已经进行了正常的前端Validation验证,而且已经验证经过了,那么若是咱们此时在调试窗口手动的去修改画面的值,那么验证将再也不有效
能够看到,手动的将【会员名】改为了空值,运行结束后看最终结果值
此时【会员名】变成空了。
那么,咱们就须要考虑一个问题,如何避免这个问题。
答案很简单,进行双重验证,客户端和服务器端都进行验证,由此咱们还须要对模型进行验证。验证方法以下:
MVC 模型注解验证
在对应的实体类的字段上加注解,如
/// <summary> /// UserName /// </summary> [DataMember] [Required(ErrorMessage = "会员名不能空")] public String UserName { get { return this.userName; } set { this.userName = value; } }
<div class="row edit-field-div"> <div class="col-sm-3 input-label"> <label for="UserName" class="control-label">会员名 <span style="color:red">*</span></label> </div> <div class="col-sm-8"> @Html.TextBoxFor(model => model.UserName, new { @class = "form-control", @autocomplete = "off" }) @Html.ValidationMessageFor(model => model.UserName,"", new { @style="color:red"}) </div>
// 保存信息 $('#frm').submit();
Form 表单在提交的时候会作后台验证,也就是对实体类的验证
其余验证以下:
转自:https://www.cnblogs.com/dianshen520/p/4349229.html
一、模型注解,用来检查表单中元素的合法性,效果相似于前面学过的 formvalidate.js插件
命名空间: using System.ComponentModel; 下面存储了
一、DisplayName():标记属性要显示的名称 配合视图上面的 @Html.DisplayNameFor(c=>c.属性名称)来显示
命名空间: using System.ComponentModel.DataAnnotations; 下面存储了
一、Required :用来作非空验证检查,特色:在非字符串类型属性上会自动加上 Required 特性标签,若是是字符串类型必须手动添加
二、StringLength :用来检查字符串类型的属性的长度验证
三、Range:用来检查数值(int,decimal,double,float)类型的属性的范围验证
四、Compare:用来比较两个属性的值是否一致,通常用于确认密码属性上
五、[RegularExpression("\\d+", ErrorMessage="年龄必须是一个数值")]:约束此属性的值必须是一个数值
命名空间: using System.ComponentModel.DataAnnotations; 下面存储了
一、Remote("请求的action名称","控制器名称",HttpMethod = "post/get(通常推荐使用post请求来防止ajax的缓存)",ErrorMessage = "提示文本"):会发出一个ajax请求到某个控制器中的某个 action进行检查操做,若是存在则返回字符串的 false (注意不能使用大写的False,若是使用了则不能正常调用)
表示此值已经存在不能再使用,不然返回true(注意不能使用大写的True,若是使用了则不能正常调用) 表示可使用
[System.Web.Mvc.Remote("CheckUserName" //表明的是请求的action名称
,"Home" //表明控制器名称
,HttpMethod="post" //表示发出post的ajax异步请求,主要是为了防止ajax请求的缓存,若是使用get可能出现结果不许确
,ErrorMessage="此值已经被使用,请从新跟换") //表示若是服务器返回的是false字符串,则提醒用户
]
eg:
/// <summary> /// 员工信息 /// </summary> public class StaffInfo { public virtual int StaffInfoId { get; set; } [Required] [Display(Name = "登陆帐号")] public virtual string LogID { get; set; } [StringLength(10, MinimumLength = 4, ErrorMessage = "{0}的长度必须大于{2}个字符并小于{1}个字符")] [Display(Name = "密码")] public virtual string LogPassword { get; set; } [StringLength(10, ErrorMessage = "{0}的长度不能大于{1}个字符")] [Display(Name = "姓名")] public virtual string RealName { get; set; } [Display(Name = "出生日期")] //[Range(typeof(DateTime), "2011-12-31", "1950-1-1", ErrorMessage = "{0}的范围是{1}到{2}")] public virtual DateTime Birthday { get; set; } [RegularExpression(@"\d{17}[\d|X]|\d{15}", ErrorMessage = "{0}的格式不正确")] [Display(Name = "身份证号码")] public virtual string IdentityNo { get; set; } [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "{0}的格式不正确")] [Display(Name = "邮箱")] public virtual string Email { get; set; } [Display(Name = "逻辑删除标识")] public virtual int IsLogicDelete { get; set; } }
总结以下:
使用Required 进行页面元素的合法性验证步骤:
一、在实体属性上打上[Required(ErrorMessage="Name属性非空")]
二、在视图页面上 利用@Html.TextBoxFor(c=>c.Name) :用来生产文本框,同时给文本框架加上 data-val="true" data-val-*......
三、在视图页面上 利用@Html.ValidationMessageFor(c=>c.Name) 用来显示提示文本的
四、引用三个js脚本
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
五、注意:元素必须放到表单中 <form> 标签才能起验证做用
六、检查MVC网站跟目录下面的web.config中的<appSettings>节点中的两个节点
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
的值必须为true,才能起验证做用,不然任何一个关闭都不起做用
七、最终表单的提交须要用form的submit()方法来进行验证(本身验证的结果)
什么叫作非嵌入式脚本(非侵入式脚本)~/Scripts/jquery.validate.unobtrusive.js
没有在视图上写一个验证的代码就完成表单元素的验证功能,仅仅只是利用了相关的脚原本完成,这个就叫作非嵌入式
OK,这样前端和后端的基本验证就作完了。
ps:开发过程当中,能够适当考虑一下前端验证存在的必要性。
// REMOTE
remote验证,保存时会有须要两次点击保存按钮,解决方案:
$('#myClientModal').on('shown.bs.modal', function (e) { $('#frmClient').data('bootstrapValidator').resetForm(false); if (!isNull($("#Id").val())) { $('html').one('mouseover', function () { //每次弹框弹起后都会进行一次校验,并且只校验一次 $('#frmClient').data("bootstrapValidator").validate(); }); } });