65.9K
CodeProject 正在变化。 阅读更多。
Home

在 MVC 4 中捕获模型, 避免往返

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2013年6月6日

CPOL

5分钟阅读

viewsIcon

27223

downloadIcon

237

一个教程, 用于在客户端捕获模型, 并使用客户端事件显示过滤后的信息, 而无需返回服务器

引言

本小型教程将为您提供避免往返服务器并获得更快页面响应的信息。

并非总是可行,但在某些情况下,我们可以避免不必要的往返服务器,并通过客户端代码来实现。一种典型情况是,我们有一个带有默认选项“全部”的组合框。在这种情况下,我们首次从服务器读取信息时,会将所有信息都获取到客户端。

这里的想法是将信息缓存在客户端的 JavaScript 全局变量中,并在此缓存信息上应用过滤器,从而避免去服务器获取过滤后的信息。

以下图片说明了此功能的一种典型用法

背景

使用 Razor 的 MVC 4 使用 Model Data 对象来传输用于渲染 HTML 页面的信息,但在页面在服务器上渲染后,Model 对象将不再存在。因此,我们的第一个目标是在页面在服务器上渲染时,将 Model 对象传递到一个全局 JavaScript 变量。

JavaScript 支持 JSON 格式,因此我们需要将模型转换为 JSON 模型,并将其存储在全局 JavaScript 变量中。然后,使用客户端代码,我们可以捕获组合框或列表框的“onchange”事件,并执行必要的过滤操作来显示数据。我们使用 JQuery 和 JavaScript 的组合来实现此目的。

您可以下载简单的示例以更好地了解此过程。

Using the Code

重要提示:如果您在项目中使用此代码,请确保您已将 System.Web.Helpers 添加为引用,并且非常重要的是,在属性中检查“复制本地”是否为 true

为了演示此功能,我们使用了一个显示不同国家/地区不同“团队”的数据模型。我们的任务是构建一个网页,显示所有团队,并且还可以显示特定国家/地区的团队。我们使用以下模型来传递信息到视图。

重要提示:请注意,将用作组合框项目的国家/地区是作为 SelectListItem 的列表创建的。如果您想使用 HTML 帮助程序创建组合框,则应使用此类。

using System.Collections.Generic;
using System.Web.Mvc;

namespace NoRoundTrip.Models
{
    /// <summary>
    /// Model for Index - Model action.
    /// </summary>
    public class IndexHomeModel
    {
        /// <summary>
        /// List of all countries.
        /// </summary>
        public IList<SelectListItem> Countries { get; set; }

        /// <summary>
        /// List of all team of all countries
        /// </summary>
        public IList<Team> ListTeam { get; set; }

        /// <summary>
        /// Page Title.
        /// </summary>
        public string PageTitle { get; set; }
    }

    public class Team
    {
        public string TeamName { get; set; }
        public string Country { get; set; }
    }
}

实现此功能的第一步是创建一个控制器操作,该操作在视图中返回一个 Model 对象,如以下代码所示

using System.Web.Mvc;

namespace NoRoundTrip.Controllers
{
    public class HomeController : Controller
    {
         public ActionResult Index()
        {
           var model = MockDataLayer.DataLayer.GetTeamsInformationMock();
           return View(model);
        }
    }
}

在这里,我们从数据源获取数据。在示例中,数据来自模拟源,为简单起见,它返回一个固定列表。

请注意,您的视图以给定的模型作为参数。

第二步是创建视图,使用 Visual Studio(在视图上单击鼠标右键,然后在菜单中选择创建视图)。

然后,我们需要在视图上放置显示信息的必要元素。Razor 允许您将 Model 提供的值插入到您的视图中,如以下代码所示

@using System.Web.Mvc.Html
@model NoRoundTrip.Models.IndexHomeModel
@{
    ViewBag.Title = Model.PageTitle;
}
@Scripts.Render("~/bundles/jquery")
<div class="Center-Text">
    <h2>@Model.PageTitle</h2>
    @Html.DropDownList("combobox1", @Model.Countries)

    <div id="content">
    </div>
</div>

在这里,您可以观察到用来自 Countries 列表的 Countries 填充的组合框控件。此组合框名为 combobox1。这使得它可以在 JavaScript 中识别。

另一个重要的事情是带有 Id 内容的 div 标签。我们使用此区域来嵌入 JavaScript 在页面加载时生成的代码。如您所见,在此步骤中,没有生成带有组合框结果的代码。

当页面准备好发送到客户端时,服务器会生成一个 page.ready 事件。在那里,我们将模型转换为 JSON string 并将其存储在一个全局 JavaScript 变量中。

<script type="text/javascript">
    // This global variable is used to store the json representation of model in the client.
    var jmodel;
</script>

<script type="text/javascript">
    $(document).ready(function () {
         jmodel = @Html.Raw(Json.Encode(Model));
        $('#content').html(OrganizeContent(jmodel));
    });
</script>

语句 @Html.Raw(Json.Encode(Model)); 将模型转换为 JSON 并将其存储在全局 JavaScript 变量 jmodel 中。此变量在客户端可访问,我们使用它来存储模型信息,并根据组合框选择的国家/地区选择要显示的数据部分。

注意:Visual Studio 2012 将 @Html.Raw.(Json.Encode(Model)); 的结尾标记为语法错误,这是一个已知的 VS bug。忽略它,项目应该可以编译而不会出错。

最后一行 jQuery 代码将必要的 HTML 插入到 id = content 的标签中,以列出团队信息。

我们使用以下 JavaScript 代码作为示例来格式化团队列表

<script type="text/javascript">
function OrganizeContent(mod) {
     var list = [];
     var e = document.getElementById("combobox1");
     var indexselected = e.options[e.selectedIndex].text;
     if (indexselected != "All") {
        for (x in mod.ListTeam) {
            var item = mod.ListTeam[x];
            if (item.Country == indexselected) {
               list.push(item);
            }
        }
    } else {
       list = mod.ListTeam;
    }

    // Create the html to be show
    var html = '<div id= "table"><p></p>';
    for (var i = 0; i < list.length; i++) {
        html += '<div>' + list[i].TeamName + '</div>';
    }

    html += '<div>';
    return html;
}
</script>

该代码根据组合框控件中显示的文本创建团队列表。您也可以使用 Value 元素。在本例中,我们使用文本(请注意,当 Model 对象转换为 JSON 时,Text 会转换为 text)。

重要提示:请注意,Model 的列表已转换为数组。

现在,作为最后一步,我们需要为组合框的客户端事件 onchange 创建一个处理 JavaScript 函数,该函数简单地调用 OrganizeContent,以更新组合框选定的项目并重绘 content 标签内的代码。

<script type="text/javascript">
    // This jquery function is triggered when the combo box changes text.
    $(function () {
        $('#combobox1').change(function() {
            $('#content').html(OrganizeContent(jmodel));
        });
    });
</script>

就这样。然后,您将看到如图 1 所示的屏幕。

关注点

在这里,我们开发了一个页面,该页面使用从服务器传递的相同信息来显示过滤后的信息,而无需再次访问服务器。

这在要显示的信息量不是特别大,或者您一开始就显示信息而不使用过滤器(即组合框中的“全部”选项)时特别有用。

如果信息量非常大,您应该考虑将所有信息传递到客户端所需的时间延迟,而不是通过往返服务器来传递部分信息。

历史

  • 第一版
© . All rights reserved.