在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
3.2.3 带视图模型的强类型视图 当使用基于Razor的视图时,视图默认继承两个类型:System.Web.Mvc.WebViewPage或者System.Web.Mvc.WebViewPage<T>。泛型WebViewPage<T>继承自WebViewPage,但是提供了一些非泛型WebViewPage类里没有的独特的补充。 下面展示了WebViewPage<T>的主干成员定义:
清单 3.3
public class WebViewPage<TModel> : WebViewPage { public new AjaxHelper<TModel> Ajax { get; set; } public new HtmlHelper<TModel> Html { get; set; } public new TModel Model { get; } public new ViewDataDictionary<TModel> ViewData { get; set; } }
除了通过Model属性在ViewData.Model之上提供了一个强类型包装器外,WebViewPage<T>类还提供访问关联视图的帮助器对象的强类型版本,AjaxHelper和HtmlHelper。 要使用强类型视图,首先你必须确保控制器动作正确设置了ViewData.Model。在清单3.4里,我们获取所有的留言记录,显示在列表页面,并传递个人档案的整个集合到View方法,此方法封装了对ViewData.Model属性的设置。
清单 3.4
public ActionResult Index() { var mostRecentEntries = (from entry in _db.Entries orderby entry.DateAdded descending select entry).Take(20); var model = mostRecentEntries.ToList(); return View(model); }
在与这个动作相应的Index视图里,即使松散类型的WebViewPage类也能使用ViewData.Model属性。但是这个属性只是一个object类型,我们需要对它进行转换以便有效地使用它。作为替代方案,我们能用@model关键词指定模型的类型。
@using Guestbook.Models 通过用@model关键词指定模型的类型,我们的视图现在继承自WebViewPage<T>而不是WebViewPage,我们有了一个强类型视图。我们也用@using关键词导入名字空间。在下一部分,我们将看到如何使用模型对象在视图里显示信息。
3.2.4 一般要在视图里显示信息,你可以使用HtmlHelper对象帮助获得视图模型以生成HTML。考虑下下面的清单,我们呈现了一个完整的留言板记录。 清单 3.5
<h2>Guestbook Entry</h2> <dl> <dt>Name:</dt> <dd>@Model.Name</dd> <dt>Date Added:</dt> <dd>@Model.DateAdded</dd> <dt>Message:</dt> <dd>@Model.Message</dd> </dl> <p> @{ bool hasPermission = (bool) ViewData["hasPermission"]; } @if (hasPermission) { @Html.ActionLink("Edit", "Edit", new {id = Model.Id}) } @Html.ActionLink("Back to Entries", "Index") </p> 在这里,我们显示在模型里传递的留言板详细信息。接着,我们用Razor多行代码语句从ViewData中获取”hasPermission“的值。Razor多行语句用at符号后跟一个大括号来开始一个代码块:@{。最后,我们用一个Razor的if块来有条件的显示Edit链接。因为当在屏幕上显示未编码的用户输入时有可能遭到各种脚本攻击,所以数据在呈现到屏幕以前默认是被自动编码的。为了显示未编码的信息,我们可以使用Html.Raw方法强制显示原生文本。 在登录页面,我们用一个视图模型对象代表完整的表单,就像下面清单显示的: 清单 3.6
public class LogOnModel { [Required] [Display(Name = "User name")] public string UserName { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [Display(Name = "Remember me?")] public bool RememberMe { get; set; } } LogOnModel类很简单,只包括必须的属性。你在这里看到的特性是数据注解,关于它们更多的内容会在第4章学到。对于每一个属性在登录页面都会显示一个输入元素,如图3.2所示。 图3.2 登录页
因为我们为登陆页选择了强类型视图,我们能用内建的帮助器来为每一个输入元素绘制出HTML。取代松散的绑定到代表动作参数的字符串,我们能利用基于表达式的HtmlHelper扩展创建各种类型的输入元素,如下: 清单 3.7
@using (Html.BeginForm()) { @Html.ValidationSummary(true, "Account creation was unsuccessful. " + "Please correct the errors and try again.") <div> <fieldset> <legend>Account Information</legend> <div class="editor-label"> @Html.LabelFor(m => m.UserName) </div> <div class="editor-field"> @Html.TextBoxFor(m => m.UserName) @Html.ValidationMessageFor( m => m.UserName) </div> <div class="editor-label"> @Html.LabelFor(m => m.Email) </div> <div class="editor-field"> @Html.TextBoxFor(m => m.Email) @Html.ValidationMessageFor(m => m.Email) </div> <div class="editor-label"> @Html.LabelFor(m => m.Password) </div> <div class="editor-field"> @Html.PasswordFor(m => m.Password) @Html.ValidationMessageFor(m => m.Password) </div> <div class="editor-label"> @Html.LabelFor(m => m.ConfirmPassword) </div> <div class="editor-field"> @Html.PasswordFor(m => m.ConfirmPassword) @Html.ValidationMessageFor(m => m.ConfirmPassword) </div> <p> <input type="submit" value="Register" /> </p> </fieldset> </div> } 在先前的清单里,我们为强类型视图页面使用了几个HtmlHelper的扩展方法,这些方法分别针对标签,输入框和验证信息。取代用松散类型的字符串代表属性,在asp.net mvc 1里就是这样使用( @Html.TextBox("UserName")),这些帮助器方法利用c# 3.5的表达式来生成HTML。因为这些生成的HTML元素需要与对象中的属性匹配,所以只适合用于原生的类型和与表达式一起使用的对象。 在清单3.7里Html.LabelFor和Html.TextBoxFor方法为UserNam属性产生HTML: 清单3.8
<label for="UserName">User name</label> <input id="UserName" name="UserName" type="text" value="" /> 为了让我们的页面通过可访问性验证,每一个输入元素(如清单3.8的第二行)需要包含一个相应的标签元素(如第一行)。因为我们的标签和输入元素都是用表达式生成的,所以我们不再担心标签和输入名称硬编码的问题。 表格3.1列出了用于强类型视图的HtmlHelper的各种扩展方法。
表格3.1
由于我们的表单是用强类型视图生成的,我们可以在设计表单post的动作上利用这一点。不用枚举每个输入域的值作为动作方法的参数,我们可以把所有的参数都绑定到与呈现视图同一个的视图模型上,如下所示。 清单3.9
public ActionResult LogOn(LogOnModel model, string returnUrl) { // Action method body here ... } 正如你看见的,LogOn动作方法使用单个LogOnModel对象,以及要返回的URL,而不是为表单里的每个输入元素用一个方法参数。 HtmlHelper扩展可能是强大的,但如果只依赖这些扩展产生HTML,在视图里仍然会引入了相当多的重复。例如,如果每个输入元素需要一个相应的标签,为什么不总是包括它呢?每个用户界面是不同的,所以MVC团队不能预知每个人所用的输入和标签元素的布局。虽然每个输入元素都应该有一个标签,现有的创建输入元素的辅助方法不适合包括标签元素。作为替代方案,我们可以利用在asp.net mvc 2里介绍的功能——模版——用一种标准化的方式产生HTML。 |
请发表评论