ViewData有一個ModelState的屬性,這是一個類型為ModelStateDictionary的ModelState類型的字典集合。在進行數據驗證的時候這個屬性是比較有用的。在使用Html.ValidationMessage()的時候,就是從ViewData.ModelState中檢測是否有指定的KEY,如果存在,就提示錯誤信息。
ModelState的內容何時被修改:
模型綁定時; 每一個值在模型狀態中都有相應的一條記錄。可以隨時查看綁定狀態
MVC控制器中語句賦值,例如 ModelState.AddModelError("Password","密碼錯誤");
ModelState的屬性
Errors :返回一個 ModelErrorCollection 對象,該對象包含在模型綁定期間發生的所以錯誤【綁定后驗證,所以錯誤】
Value:返回一個 ValueProviderResult 對象,該對象封裝在模型綁定期間綁定的值。例如模型錯誤,重新回到輸入界面時原來輸入的值會顯示
錯誤有模型級和屬性級:
ModelState.IsValid
ModelState.IsValidField("Name")
Html 輔助方法和ModelState集成
HTML 輔助方法,如Html.TextBox(),在輸出內容時,會檢查ModelState集合。如果發現該屬性有異常或錯誤,將呈現用戶輸入的內容和CSS錯誤類。
例如,在Edit視圖中,我們使用Html.TextBox() 輔助方法呈現Dinner對象的EventDate屬性:
<%= Html.TextBox("EventDate", String.Format("{0:g}", Model.EventDate)) %>
當有錯的時候呈現視圖時,Html.TextBox() 方法檢查ModelState集合,檢查是否有錯誤關聯到Dinner 對象的EventDate屬性。當發現有錯誤時,將顯示用戶提交的”EntLib” 輸入作為參數值,同時對<input type=”textbox” />元素添加CSS 錯誤類,如下所示:
<input class="input-validation-error" id="EventDate" name="EventDate"
type="text" value="BOGUS" />
你可以定制CSS錯誤類的樣式。默認的CSS錯誤類 – input-validation-error定義在\content\site.css 文件中,樣式定義如下:
.input-validation-error { border: 1px solid #ff0000; }
Html.ValidationMessage() 輔助方法
Html.ValidationMessage() 輔助方法用來輸出特定Model屬性相關的ModelState錯誤信息:
<%= Html.ValidationMessage("EventDate") %>
上述代碼輸出:
<span class=”field-validation-error”> The value ‘EntLib’ is invalid</span>
Html.ValidationMessage() 輔助方法也支持第二個參數,允許開發人員覆蓋錯誤消息:
<%= Html.ValidationMessage("EventDate", "*") %>
上述代碼輸出:
<span class=”field-validation-error”> *</span>,而不是默認的錯誤信息。
Html.ValidationSummary() 輔助方法
Html.ValidationSummary() 輔助方法將呈現總結的錯誤消息,通過<ul><li/></ul>元素列出在ModelState集合中所有詳細的錯誤消息
Html.ValidationSummary() 輔助方法接收一個可選的字符串參數 – 定義一個概括性的錯誤消息,並顯示在所有詳細錯誤信息的前面:
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
你也可以定義CSS設置錯誤消息的樣式。
使用AddRuleViolations輔助方法
初始的HTTP-POST Edit的實現方法使用了一個foreach循環語句,遍歷Dinner對象的Rule Violations,並添加到controller的ModelState集合:
catch { foreach (var issue in dinner.GetRuleViolations()) { ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage); } return View(dinner); }
為了使代碼更簡潔一點,我們添加ControllerHelpers類到NerdDinner項目中,並實現了AddRuleViolations擴展方法,添加了一個對ASP.NET MVC ModelStateDictionary 類的輔助方法。該擴展方法封裝了使用RuleViolation 錯誤信息填充ModelStateDictionary 集合類的邏輯:
public static class ControllerHelpers { public static void AddRuleViolations(this ModelStateDictionary modelState,IEnumerable<RuleViolation> errors) { foreach (RuleViolation issue in errors) { modelState.AddModelError(issue.PropertyName, issue.ErrorMessage); } } }
接下來,我們更新HTTP-POST Edit方法,使用上述擴展方法實現Dinner的Rule Violations填充ModelState集合。
完成Edit Action方法的實現
下面的代碼實現了控制器中Edit的所有邏輯:

// // GET: /Dinners/Edit/2 public ActionResult Edit(int id) { Dinner dinner = dinnerRepository.GetDinner(id); return View(dinner); } // // POST: /Dinners/Edit/2 [AcceptVerbs(HttpVerbs.Post)] public ActionResult Edit(int id, FormCollection formValues) { Dinner dinner = dinnerRepository.GetDinner(id); try { UpdateModel(dinner); dinnerRepository.Save(); return RedirectToAction("Details", new { id = dinner.DinnerID }); } catch { ModelState.AddRuleViolations(dinner.GetRuleViolations()); return View(dinner); } }
關於Edit方法的實現的優點,不僅Controller類,而且View視圖模板都不必關心Dinner模型類的特定驗證方法或者業務規則。以后,我們可以針對Model類增加額外的業務規則,而不必要求Controller和View更改代碼。這樣,我們可以根據需求,以最小的更改代碼量,靈活改進應用程序。