zoukankan      html  css  js  c++  java
  • 2asp.net mvc 4 in action

    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 { getset; }
    public new HtmlHelper<TModel> Html { getset; }
    public new TModel Model { get; }
    public new ViewDataDictionary<TModel> ViewData { getset; }
    }
    复制代码

     

    除了通过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 List<GuestbookEntry>

    通过用@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 { getset; }
    [Required]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { getset; }
    [Display(Name = "Remember me?")]
    public bool RememberMe { getset; }
    }
    复制代码

    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

    •  DisplayFor
    • DisplayTextFor
    • EditorFor
    • CheckBoxFor
    • DropDownListFor
    • HiddenFor
    • LabelFor
    • ListBoxFor
    • PasswordFor
    • RadioButtonFor
    • TextAreaFor
    • TextBoxFor
    • ValidateFor
    • ValidationMessageFor

    由于我们的表单是用强类型视图生成的,我们可以在设计表单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。

     
     
    标签: asp.net mvc
  • 相关阅读:
    bzoj 3709: [PA2014]Bohater【贪心】
    bzoj 3714: [PA2014]Kuglarz【最小生成树】
    bzoj 2216: [Poi2011]Lightning Conductor【决策单调性dp+分治】
    bzoj 2087: [Poi2010]Sheep【凸包+极角排序+dp】
    bzoj 3830: [Poi2014]Freight【dp】
    bzoj 3930: [CQOI2015]选数【快速幂+容斥】
    bzoj 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式【后缀自动机】
    bzoj 1614: [Usaco2007 Jan]Telephone Lines架设电话线【二分+spfa】
    bzoj 1640||1692: [Usaco2007 Dec]队列变换【后缀数组】
    bzoj 1612: [Usaco2008 Jan]Cow Contest奶牛的比赛【Floyd】
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2563038.html
Copyright © 2011-2022 走看看