MVC神韵---你想在哪解脱!(十六)
MVC验证属性自动验证原理
也许有人会问,既然我们没有在C与V追加任何显示错误信息提示的代码,那么控制器或视图内部是如何生成这些显示错误信息提示的画面的。让我们揭开这么谜底吧!当在Movie类中追加了验证属性规则后,我们并没有修改这个类中的任何代码!要揭开这个谜底,首先让我们看看MovieController类中的代码:
1 public ActionResult Create() 2 { 3 return View(); 4 } 5 6 // 7 // POST: /Movies/Create 8 9 [HttpPost] 10 public ActionResult Create(Movie newMovie) 11 { 12 if (ModelState.IsValid) 13 { 14 db.Movies.Add(newMovie); 15 db.SaveChanges(); 16 17 return RedirectToAction("Index"); 18 } 19 else 20 { 21 return View(newMovie); 22 } 23 }
问题就出在ModelState.IsValid属性上,(当然此属于在应用中也有问题。比如安全考虑我们对自动绑定进行了限制,而没用上或没绑定的不验证时,此属性会出错)。ModelState.IsValid属性用来判断是否提交的电影数据中包含有任何没有通过数据验证的无效数据。如果存在无效数据,Create方法重新返回追加电影视图。如果数据全部有效,则将该条数据保存到数据库中。我们之前创建的使用支架模板的Create.cshtml视图模板中的代码显示如下,在首次打开追加电影视图与数据没有通过验证时,Create方法中返回的视图都是使用的这个视图模板。
1 @model MvcMovie.Models.Movie 2 @{ 3 ViewBag.Title = "追加电影信息"; 4 } 5 <h2>追加电影信息</h2> 6 <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 7 type="text/javascript"></script> 8 <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" 9 type="text/javascript"></script> 10 11 @using (Html.BeginForm()) { 12 @Html.ValidationSummary(true) 13 <fieldset> 14 <legend>电影</legend> 15 <div class="editor-label"> 16 标题 17 </div> 18 <div class="editor-field"> 19 @Html.EditorFor(model => model.Title) 20 @Html.ValidationMessageFor(model => model.Title) 21 </div> 22 <div class="editor-label"> 23 发行日期 24 </div> 25 <div class="editor-field"> 26 @Html.EditorFor(model => model.ReleaseDate) 27 @Html.ValidationMessageFor(model => model.ReleaseDate) 28 </div> 29 <div class="editor-label"> 30 种类 31 </div> 32 <div class="editor-field"> 33 @Html.EditorFor(model => model.Genre) 34 @Html.ValidationMessageFor(model => model.Genre) 35 </div> 36 <div class="editor-label"> 37 票价 38 </div> 39 <div class="editor-field"> 40 @Html.EditorFor(model => model.Price) 41 @Html.ValidationMessageFor(model => model.Price) 42 </div> 43 <p> 44 <input type="submit" value="追加" /> 45 </p> 46 </fieldset> 47 } 48 <div> 49 @Html.ActionLink("返回电影列表", "Index") 50 </div>
可以看到在许多页面控件后面紧跟着一个Html.ValidationMessageFor辅助方法。此方法自动寻找指定给模型的各个验证属性,然后显示对应的验证错误信息。这种验证体制的好处是在于控制器和Create视图(追加电影视图)事先都即不知道实际指定的验证规则,也不知道将会显示什么验证错误信息。验证规则和错误信息只在Movie类中被指定。如果我们之后想要改变验证规则,我们也只要在Model模型类中进行改变就可以了。我们不用担心整个应用程序中存在验证规则不统一的问题,所有的验证规则都可以集中在一处地方进行指定,然后在整个应用程序中使用这些验证规则。这将使我们的代码更加清晰明确,更加具有可读性、可维护性与可移植性。这将意味着我们的代码是真正符合DRY原则(一处指定,到处可用)。
附录:
当某些字段很重要,为了安全不允许自动绑定以防止黑客篡改客户端,通过自动绑定了解需要保密的某些属性字段。所以我们对自动绑定进行了限制,通过[Bind(Include="")]来设置允许自动绑定的字段,而ModelState.IsValid属性就不能继续使用了,不然一定会出错。此时要用TryUpdateModel()方法来替换!