• 知识点3-4:给视图传递数据


        控制器中加工处理好的数据,如何传递给视图? 

    一、ViewDataDictionary

        用来将模型信息传递给视图的主要对象是ViewDataDictionary类,它暴露了一个字典,以使控制器动作能够把任意数目的模型对象和信息传递给视图。借助字典对象,我们可以传递需要的数据到视图。

        举个栗子>>:如何扩展留言本网站,使任何人都能查看留言,但只有当前已登录用户能够编辑留言本条目。

        目前显示留言本信息,我们可以把GuestbookEntry形式的对象直接传递给视图,GuestbookEntry如下所示。

    public class GuestbookEntry
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public string Message { get; set; }
            public DateTime DateAdded { get; set; }
        }

        尽管这个GuestbookEntry类拥有显示GuestbookEntry所需的全部信息,但它并未包含当前已登录用户的任何信息,或指示视图是否应该显示Edit链接的信息。这就需要给视图提供更多数据,而不只是GuestbookEntry对象。我们可以使用ViewDataDictionary来提供这种额外的信息片段,如下所示。

            public ViewResult Show(int id)
            {
                var entry = _db.Entries.Find(id);
                bool hasPermission = User.Identity.Name == entry.Name;
                ViewData["hasPermission"] = hasPermission;
                return View(entry);
            }

        上例检查了当前用户名,将它与留言本条目的Name属性进行比较,并将比较结果放入用hasPermission键表示的ViewData中。接着用重载的View方法创建一个ViewResult对象,并将ViewData的Model属性设置为GuestbookEntry对象。

        在视图一侧,我们将取出ViewData中的hasPermission信息,并用它隐藏Edit链接,如下所示。

    <h2>Guestbook Entry</h2>
    <dl>
        <dt>Name:</dt>
        <dd>@Model.Name</dd>
    
        <dt>Data 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>

        在这个视图中,我们从ViewData提取了hasPermission信息。接着,根据hasPermission变量,有条件地显示了Edit链接。最后,显示了一个将用户带回留言本条目列表页面的链接。显示留言本条目的最终渲染页面如下图所示。

        虽然ViewDataDictionary非常灵活,但在语法上并不太好用,只要从字典接受数据,就必须执行类型转换。

    二、ViewBag

        与ViewDataDictionary一样,ViewBag也提供了一种方式,以便将数据从控制器传递给视图,但ViewBag利用了C#4的动态语言特性。它并非使用字符串键在一个字典中存储数据项,你可以在控制器中简单地在这个动态的ViewBag属性上设置若干属性:

    ViewBag.HasPermission = hasPermission;

        ViewBag属性在视图中也是可用的,因此不必从ViewData接受数据项,并将它转换成Boolean型,我们可以简化视图,直接访问ViewBag:

    <p>
        @if(ViewBag.HasPermission)
            {
                @Html.ActionLink("Edit","Edit", new { id=Model.Id})
            }
            @Html.ActionLink("Back to Entries", "Index")
        }
    </p>

        尽管ViewData和ViewBag这两种动态方法都提供了许多灵活性,但这是有代价的。如果偶然输错了一个动态属性名,这些技术既不能友好重构,编译器也不能测出这类错误。此外,对于动态属性或ViewData,你得不到Visual Studio的智能感应。

        另外,你不能方便地将元数据附加到动态属性上。模型验证规则也不能用于动态的ViewBag属性。作为一种可选办法,你可以利用强类型视图,以指示视图能够使用一个特定的已知强类型类。这样可以利用智能感应和Visual Studio的重构工具,并且也可以使用模型验证规则。

    三、带有视图模型的强类型视图

        在使用基于Razor的视图时,默认情况下,视图继承于两种类型:System.Web.Mvc.WebViewPage或System.Web.Mvc.WebViewPage<T>,继承于WebViewPage的视图称为弱类型视图,继承与WebViewPage<T>的视图为强类型视图。

        WebViewPage<T>的定义如下所示。

        除了通过Model属性提供对ViewData.Model的强类型封装之外,还对相关的视图辅助器对象AjaxHelper和HtmlHelper的强类型版本提供了访问。为了使用强类型视图,首先必须确保控制器动作适当地设置了ViewData.Model。

        练习>>:将Guestbook程序中的Index视图修改为强类型视图。

        在清单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关键字,为WebViewPage<T>基类指定模型类型。

    @using Guestbook.Models
    @model List<GuestbookEntry>
    
    @{
        ViewBag.Title = "查看留言";
    }
    
    <h2>请给我留言吧</h2>
    <p>
        <a href="/Guestbook/Create">添加留言</a>
    </p>
    @foreach(var entry in Model)
    {
        <section class="contact">     
            <header>
                <b>作者:</b>@entry.Name; <b>时间:</b>@entry.DateAdded.ToLongDateString()
            </header> 
            <p><b>留言内容:</b>@entry.Message</p>
        </section>
        <hr />
    }

        通过使用@model关键字指定模型类型,视图便是继承于WebViewPage<T>,而不是WebViewPage了,于是得到了一个强类型视图。这里还使用了@using关键字,以导入命名空间。

    总结>>:从Action取得数据,在ASP.NET MVC可区分成两种方式,一种是“使用弱类型取得数据”,另一种则是“使用强类型取得数据”,两者的差别在于View页面最上方声明的方式。

        如果View页面使用弱类型接收来自Controller的数据,在View页面里完全不需要有任何声明,数据可以从ViewData、ViewBag或TempData取得,在页面中也可以通过@Model属性,取得从Action传来的ViewData.Model数据模型,但@Model数据模型的类型将会是object,所以算是弱类型的传值方式。

        如果View页面使用强类型方式接收来自Controller的数据,那么,必须在View页面的第一行使用@model关键字引入一个View页面专用的数据模型类型参考。使用这种方式有助于提升View的开发效率,因为可以使用Visual Studio 2012的Intellisense提示功能。

  • 相关阅读:
    Linux企业级项目实践之网络爬虫(12)——处理HTTP应答头
    Linux企业级项目实践之网络爬虫(11)——处理http请求头
    Linux企业级项目实践之网络爬虫(10)——处理HTTP状态码
    求区间最大子段和(线段树)
    求区间最大子段和(线段树)
    琐碎的知识点(xly)
    无源汇有上下界可行流(网络流进阶)
    bzoj2463谁能赢呢?
    bzoj2463谁能赢呢?
    日常(崩溃的边缘)
  • 原文地址:https://www.cnblogs.com/meetyy/p/3999155.html
Copyright © 2020-2023  润新知