.NET MVC 學習筆記(五)— Data Validation

.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">卡號&nbsp<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">會員名&nbsp<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">性別&nbsp<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">出生日期&nbsp<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">手機號&nbsp<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">會員名&nbsp<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();
		});
	}
}); 
相關文章
相關標籤/搜索