前五篇博文分別介紹並實現了前端校驗和服務器校驗,這篇博文主要是介紹如何將二者結合起來使用,並總結。javascript
以前,咱們在ASP.NET MVC中集成了基於FluentValidator的驗證器,並經過擴展Controller,在ControllEx中 使用 OnActionExecuting 進行統一校驗。最後將全部錯誤信息存放在ViewData["Error"]內部後返回視圖。html
在視圖呈現方面,咱們使用了HtmlHelper的擴展方法來幫呈現,這樣有效避免了Null的尷尬局面。前端
/// <summary> /// 顯示指定屬性的錯誤消息 /// </summary> /// <param name="htmlHelper">HtmlHelper</param> /// <param name="property">指定的屬性</param> /// <param name="error">ViewData["Error"]</param> /// <param name="tagType">標籤類型</param> /// <param name="htmlAttribute">標籤屬性</param> /// <returns></returns> public static MvcHtmlString ValidatorMessageFor(this HtmlHelper htmlHelper, string property, object error, string tagType = "p", object htmlAttribute = null) { var dicError = error as Dictionary<string, string>; if (dicError != null) //沒有錯誤 { if (dicError.ContainsKey(property)) { StringBuilder sb = new StringBuilder(); if (htmlAttribute != null) { htmlAttribute.GetType().GetProperties().ToList().ForEach((p) => { string key = p.Name; string value = p.GetValue(htmlAttribute).ToString(); sb.AppendFormat(" {0}='{1}' ", key, value); }); } return new MvcHtmlString(string.Format("<{0} {2}>{1}</{0}>", tagType, dicError[property], sb.ToString())); } } return new MvcHtmlString(""); }
現在我對HtmlHelper作了必定修改,使它支持自定義標籤類型和定義Html的屬性,這會讓咱們好的管理呈現效果。比方爲他加一個樣式。vue
經過以上步驟咱們就實現了服務端的驗證。java
在前端,與前幾章說講的同樣,咱們使用Vue,並自編寫了基於Vue的驗證插件vuefluentvalidator,爲何叫它vuefluentvalidator,由於編寫它的時候就是借鑑的我們後臺驗證框架FluentValidator的使用方式。後端
@using ValidationWebTest.Mvc.MvcHelperEx @{ ViewBag.Title = "ValidatorTest"; } <h2>ValidatorTest</h2> <div id="box"> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Person</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> <label for="Name" class="control-label col-md-2">姓名</label> <div class="col-md-10"> <input type="text" name="Name" class="form-control" v-model="model.name" /> <p v-text="model.error.name"></p> @Html.ValidatorMessageFor("Name", ViewData["Error"], "span", new { @class = "text-info" }) </div> </div> <div class="form-group"> <label for="Age" class="control-label col-md-2">年齡</label> <div class="col-md-10"> <input type="text" name="Age" class="form-control" v-model="model.age" /> <p v-text="model.error.age"></p> @Html.ValidatorMessageFor("Age", ViewData["Error"], "strong") </div> </div> <div class="form-group"> <label for="Home" class="control-label col-md-2">住址</label> <div class="col-md-10"> <input type="text" name="Address.Home" class="form-control" v-model="model.address.home" /> <p v-text="model.error.address.home"></p> @Html.ValidatorMessageFor("Address.Home", ViewData["Error"]) </div> </div> <div class="form-group"> <label for="Phone" class="control-label col-md-2">電話</label> <div class="col-md-10"> <input type="text" name="Address.Phone" class="form-control" v-model="model.address.phone" /> <p v-text="model.error.address.phone"></p> @Html.ValidatorMessageFor("Address.Phone", ViewData["Error"]) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default" v-on:click="formSubmit($event)" /> </div> </div> </div> } </div> @section scripts{ <script src="~/Content/vue.js"></script> <script src="~/Content/vuefluentvalidator.js"></script> <script> let vm = new Vue({ el: '#box', data: { validator: new Validator({ model: { name: undefined, age: undefined, address: { home: undefined, phone: undefined }, }, rule: function (than) { than.ruleFor("name") .NotEmpty() .WithMessage("姓名不能爲空") .MinimumLength(5) .WithMessage("最短長度爲5"); than.ruleFor("age") .NotEmpty() .WithMessage("年齡不能爲空"); than.ruleFor("address.home") .NotEmpty() .WithMessage("家庭地址不能爲空"); than.ruleFor("address.phone") .NotEmpty() .WithMessage("電話不能爲空"); } }), }, methods: { formSubmit: function (ev) { if (this.validator.passValidation()) { return; } ev.preventDefault(); this.validator.validation(ev.target); } }, computed: { model: function () { return this.validator.model; } } }); </script> }
使用方式和以前前端驗證所講的都如出一轍,只是在驗證下邊加了一行服務器
@Html.ValidatorMessageFor("Name", ViewData["Error"], "span", new { @class = "text-info" })
爲何我會這樣寫?由於在正常狀況下,咱們前端會進行校驗,若是前端校驗不經過的時候,請求不會發送到後臺,因此這一行在正常狀況下是用不到的。框架
那在何時會用到他?在前端校驗失效時或僞造請求時。ui
首先分析第一種this
前端校驗失效,也就意味着javascript失效,這種狀況下咱們的
<p v-text="model.error.name"></p>
什麼都顯示不出來。
而在驗證失敗的時候 @Html.ValidatorMessageFor("Name", ViewData["Error"], "span", new { @class = "text-info" }) 就會起做用了,因爲咱們對標籤的呈現效果控制的靈活性,在視覺體驗上,沒有任何區別。
若是在第二種狀況下,他都不是一個正常的請求,我管它幹什麼?阻止就是了。
若是你認爲既然使用Vue,那爲何不將錯誤信息綁定到咱們的驗證器上呢?
事實上我也想過這麼作,一是它的工做量比如今這種方式更大(原諒我偷了個懶),二是,若是javascript失效的話,那豈不是根本顯示不出來?
綜上所述,因而我決定就讓它這樣簡單而愉快的結束吧。到此咱們的先後端校驗功能就算所有實現。
因爲博文是前五篇的延續,在一些重複的內容上,不過多介紹,若是您在閱讀時,有任何疑問,請從前面開始閱讀。