.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(); }); } });