在ASP.NET MVC中,ModelState中包含了驗證失敗的錯誤信息,具體被存儲在ModelState.Values[i].Errors[j].ErrorMessage屬性中。當然,通過打斷點,單步調試可以查看具體的驗證失敗錯誤信息,但有時候希望把ModelState中的驗證失敗信息遍歷顯示出來。
ModelState類型是ModelStateDictionary,ModelStateDictionary是一個字典集合,鍵是模型的各個屬性,值是模型各個屬性對應的ModelState。
ModelState的Errors屬性存儲了所有驗證失敗信息,是一個ModelErrorCollection類型,ModelErrorCollection是一個ModelError的集合,而ModelError的ErrorMessage屬性包含了驗證失敗錯誤信息。
大致是這樣:
○ ModelStateDictionary實際上是IDictionary<string, ModelState>類型
○ ModelState.Errors屬性實際上是ModelErrorCollection類型
○ ModelErrorCollection實際上是ICollection<ModelError>類型
○ ModelError.ErrorMessage屬性存儲着所有驗證失敗信息
如何把驗證失敗信息顯示出來呢?
{"屬性1","屬性1驗證失敗錯誤信息1"},
{"屬性1","屬性1驗證失敗錯誤信息2"},
{"屬性2","屬性2驗證失敗錯誤信息1"}
......
想寫成如上的樣子,通過json讀取出來,在后台遍歷,都可以。
那就先抽象出一個顯示錯誤信息的模型。
public class ShowError{public ShowError(string key, string message){Key = key;Message = message;}public string Key { get; set; }public string Message { get; set; }}
由於ModelState是ModelStateDictionary類型,那就針對ModelStateDictionary類型寫一個擴展方法。就是把ModelStateDictionary中的驗證失敗信息連同對應的屬性讀取出來,注入到ShowError這個模型中,並最終得到一個IEnumerable<ShowError>集合。
public static class ModelStateExtensions{public static IEnumerable<ShowError> AllModelStateErrors(this ModelStateDictionary modelState){var result = new List<ShowError>();//找到出錯的字段以及出錯信息var errorFieldsAndMsgs = modelState.Where(m => m.Value.Errors.Any()).Select(x => new {x.Key, x.Value.Errors});foreach (var item in errorFieldsAndMsgs){//獲取鍵var fieldKey = item.Key;//獲取鍵對應的錯誤信息var fieldErrors = item.Errors.Select(e => new ShowError(fieldKey, e.ErrorMessage));result.AddRange(fieldErrors);}return result;}}
再來一個最終用來測試驗證失敗錯誤信息的視圖模型。
public class Student{public int Id { get; set; }[Required(ErrorMessage = "必填")][StringLength(5, ErrorMessage = "長度1-5位")]public string Name { get; set; }[Required(ErrorMessage = "必填")]public int Age { get; set; }[Required(ErrorMessage = "必填")][Range(typeof(Decimal), "0", "100", ErrorMessage = "{0} 必須是數字介於 {1} 和 {2}之間.")]public decimal Score { get; set; }}
在HomeController中,有一個Action用來呈現Student的強類型視圖頁,有一個Action用來把從ModelState中獲取到的所有屬性以及對應的驗證失敗信息以json格式返回給前台視圖。
public class HomeController : Controller{public ActionResult Index(){return View(new Student());}[HttpPost]public ActionResult GetErrors(Student student){if (ModelState.IsValid){return Content("沒有錯誤信息~~");}Response.StatusCode = 400;Response.TrySkipIisCustomErrors = true;var modelErrors = ModelState.AllModelStateErrors();return Json(modelErrors);}}
在Home/Index.cshtml視圖中,當點擊"提交"按鈕,在控制台顯示驗證失敗信息。
@model MvcApplication1.Models.Student@{ViewBag.Title = "Index";Layout = "~/Views/Shared/_Layout.cshtml";}<h2>Index</h2>@using (Html.BeginForm("GetErrors", "Home", FormMethod.Post, new {id = "addForm"})){@Html.TextBoxFor(m => m.Name)<br />@Html.TextBoxFor(m => m.Age)<br />@Html.TextBoxFor(m => m.Score)<br /><input type="button" id="up" value="提交" />}@section scripts{<script type="text/javascript">$(function () {$('#up').on('click', function () {$.post('@Url.Action("GetErrors")', $('#addForm').serialize()).fail(function(error) {var response = JSON.parse(error.responseText);for (var i = 0; i < response.length; i++) {var e = response[i];var fieldKey = e.Key;var message = e.Message;console.log(fieldKey + ': ' + message);}});});});</script>}
最終,在控制台顯示驗證失敗信息如下:

