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

使用 jQuery 和 Json 在 ASP.NET MVC 中动态生成承载 IFrames 的选项卡

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (6投票s)

2010 年 9 月 24 日

CPOL

8分钟阅读

viewsIcon

48342

downloadIcon

1599

本文介绍了一种使用 jQuery 和 Json 在 ASP.NET MVC 中动态生成承载 IFrames 的选项卡的方法。

引言

本文介绍了一种使用 "IFrames"、"jQuery" 和 "Json" 在 "ASP.NET MVC" 中动态生成承载 IFrames 的选项卡的方法。

背景

"IFrames" 在 "Web Development" 中已被使用了很长时间,以提高网站的响应能力和用户体验。"IFrames" 还可以通过将应用程序分割成逻辑相关的块来提供一些编程优势。在某些情况下,最好将 "IFrames" 组织在 "选项卡" 中。"jQuery" 提供了一种非常好的方式来创建 "选项卡"。本文将通过一个示例介绍一种使用 jQuery 和 Json 在 ASP.NET MVC 中动态生成承载 IFrames 的选项卡的方法。

本文的灵感来自于 Matt Esterak 的文章 "使用 JQuery UI Tabs 插件承载 IFRAME"。本文利用 ASP.NET MVC 的一些新功能和 "Json" 支持来动态生成承载 IFrames 的选项卡。每个选项卡的信息在 MVC 控制器中配置,并通过 jQuery 以 Json 格式加载到客户端。

示例项目是在 "Visual Studio 2010" 和 "MVC 2" 中开发的。本例中使用的 jQuery 版本是 "1.4.2"。用于服务器端操作的语言是 "C#"。以下是 Visual Studio "解决方案资源管理器" 的屏幕截图。

Solution.JPG

ASP.NET MVC 2 项目 "DynamicJsonIFrame" 是一个简单的 Web 项目。它包含以下主要组件:

  • 在 "Models" 文件夹中,项目包含一个名为 "TabInfo" 的模型类。
  • 在 "Controllers" 文件夹中,项目包含一个名为 "HomeController" 的控制器。
  • 与 "HomeController" 对应的有三个 "视图":"Index.aspx"、"IFrameContainer.aspx" 和 "IFrameWebLoader.aspx"。"Index.aspx" 是主应用程序 Web 页面。"IFrameContainer.aspx" 和 "IFrameWebLoader.aspx" 用于创建和加载 IFrames。
  • "Index.aspx" 使用了一个名为 "Site.Master" 的母版页。

除了标准的 jQuery 库 "jquery-1.4.2.min.js" 之外,示例应用程序还需要 "jQuery Plug-in" "jquery-ui-1.8.5.custom.min.js" 和 "Stylesheet" 文件 "jquery-ui-1.8.5.custom.css"。您可以从 此处 下载这些文件。本文假设读者对 ASP.NET MVC、jQuery 和 Json 有一些基本了解。如果您对此类主题不熟悉,应该可以在网上轻松找到参考资料。

首先,让我们看一下模型类 "TabInfo"。

模型类 "TabInfo"

项目中唯一的模型类是 "TabInfo.cs" 中实现的 "TabInfo" 类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace DynamicJsonIFrame.Models
{
    public class TabInfo
    {
        public int TabID { get; set; }
        public string TabText { get; set; }
        public string TabInformationText { get; set; }
        public string TabUrl { get; set; }
    }
}

公共属性用于保存每个选项卡项的信息。"TabText" 是在选项卡项上显示的文本。"TabInformationText" 用于示例项目中选项卡项的工具提示。"TabUrl" 是激活选项卡项时要加载的网页的 URL。

控制器 "HomeController"

"HomeController" 实现如下:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using DynamicJsonIFrame.Models;
 
namespace DynamicJsonIFrame.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Index(){ return View(); }
 
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult IFrameContainer(string WebURL,
            string InformationText)
        {
            ViewData["WebURL"] = WebURL;
            ViewData["InformationText"] = InformationText;
            return View();
        }
 
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult IFrameWebLoader(string WebURL)
        {
            ViewData["WebURL"] = WebURL;
            return View();
        }
 
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult GetTabs()
        {
            List<TabInfo> tabList = new List<TabInfo>();
            tabList.Add(new TabInfo
            {
                TabID = 1,
                TabText = "Yahoo",
                TabInformationText = "",
                TabUrl = "http://www.yahoo.com"
            });
            tabList.Add(new TabInfo
            {
                TabID = 2,
                TabText = "Hall of fame",
                TabInformationText
                    = "Michael Jordan's hall of fame acceptance speech",
                TabUrl = "http://www.youtube.com/watch?v=owbYN3XstVQ"
            });
            tabList.Add(new TabInfo
            {
                TabID = 2,
                TabText = "Soccer Game",
                TabInformationText = "The greatest soccer goal",
                TabUrl = "http://www.youtube.com/watch?v=MsAgu45qqWE"
            });
            tabList.Add(new TabInfo
            {
                TabID = 2,
                TabText = "Cool",
                TabInformationText = "Soccer and soccer !",
                TabUrl = "http://www.youtube.com/watch?v=X5SwdvUWx0E"
            });
 
            return Json(tabList);
        }
    }
}

在此控制器中,有四个 "Action Methods"。"Index"、"IFrameContainer" 和 "IFrameWebLoader" 这三个 Action Methods 是标准的 Action Methods。这三个 Action Methods 中的每一个都只是返回一个 "ActionResult",将程序流程引导到 "Views\Home" 文件夹中的相应视图。最后一个 Action Method "GetTabs" 没有对应的视图。它返回一个 "JsonResult"。我将几个 "TabInfo" 对象硬编码到一个 "List" 中。在真实的 Web 应用程序中,这个 List 可以从任何配置源(例如数据库)动态创建。此 Action Method 将从 "Index.aspx" 中的一个 jQuery 客户端通过 Ajax 调用进行访问。

"Index.aspx" 视图和 "Site.Master"

在看 "Index.aspx" 之前,让我们先看一下 "Site.Master"。

 <%@ Master Language="C#"
    Inherits="System.Web.Mvc.ViewMasterPage" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>
 <asp:ContentPlaceHolder ID="TitleContent" runat="server" />
    </title>
    <link rel="SHORTCUT ICON"
        href="<%= Url.Content("~/Images/pig_mac_archigraphs.ico") %>" />
    <link rel="stylesheet" type="text/css"
        href="<%= Url.Content("~/Styles/AppStyle.css") %>" />
    <link rel="stylesheet" type="text/css"
        href="<%= Url.Content("~/Styles/jquery-ui-1.8.5.custom.css") %>" />
 
    <script type="text/javascript"
        src="<%= Url.Content("~/Scripts/jquery-1.4.2.min.js") %>">
    </script>
    <script type="text/javascript"
        src="<%= Url.Content("~/Scripts/jquery-ui-1.8.5.custom.min.js") %>">
    </script>
</head>
 
<body>
    <div>
        <div>
            <div id="Header">
                <h1>Dynamic Creation of Tabs for IFrames using
                     jQuery and Json in MVC</h1>
                <label class="Author">Developed By Song Li
                    - 9/23/2010</label>
            </div>
        </div>
        <div>
            <asp:ContentPlaceHolder ID="MainContent" runat="server" />
        </div>
        <div id="Footer"><h1>The Code Project Open License (CPOL)
             2010 - 2020®</h1></div>
    </div>
</body>
</html>

除了显示 Web 应用程序的页眉和页脚之外,"Site.Master" 还有一个名为 "MainContent" 的 "ContentPlaceHolder"。"Index.aspx" 将使用此 "ContentPlaceHolder" 向 Web 应用程序添加 HTML 和 JavaScript 内容。"Index.aspx" 实现如下:

<%@ Page Language="C#"
    MasterPageFile="~/Views/Shared/Site.Master"
    Inherits="System.Web.Mvc.ViewPage" %>
 
<asp:Content ID="TitleContent"
    ContentPlaceHolderID="TitleContent" runat="server">
    IFrame host with dynamically generated jQuery Tabs
</asp:Content>
 
<asp:Content ID="MainContent"
    ContentPlaceHolderID="MainContent" runat="server">
 
<!-- This is the place holder for the dynamically generated tabs -->
<div id="MainTabs" class="FluidContent">
    <div id="divTabs" class="iframeMax"></div>
</div>
 
<script type="text/javascript">
    var GetTabsUrl = '<%: Url.Action("GetTabs", "Home") %>';
    var IFrameContainerUrl = '<%: Url.Action("IFrameContainer", "Home") %>';
 
    $(document).ready(function () {
 
        $.ajax({
            cache: false,
            type: "POST",
            url: GetTabsUrl,
            dataType: "json",
            success: function (data) {
                var GenerateTabs = function () {
                    var tabui = document.createElement("ul");
                    $.each(data, function () {
                        var li = document.createElement("li");
                        var a = document.createElement("a");
                        a.href = IFrameContainerUrl + "?WebURL="
                            + escape(this.TabUrl)
                            + "&InformationText="
                            + escape(this.TabInformationText);
                        var span = document.createElement("span");
                        $(span).attr("title", this.TabInformationText);
                        var tx = document.createTextNode(this.TabText);
 
                        span.appendChild(tx)
                        a.appendChild(span);
                        li.appendChild(a);
                        tabui.appendChild(li);
                    });
 
                    $("#divTabs").html("").append(tabui);
 
                    var $tabs = $("#divTabs").tabs({
                        cache: true,
                        selected: -1,
                        select: function (event, ui) {
                            return true;
                        }
                    }).ajaxComplete(function (event, request, settings) {
                        return;
                    });
 
                    if (data.length > 0) {
                        $tabs.tabs('select', 0);
                    }
                };
 
                GenerateTabs();
            },
            error: function (xhr) {
                var status = xhr.status;
                var responseText = xhr.responseText;
                alert("Error occurred when load the information for the tabs");
            }
        });
 
    });
</script>
</asp:Content>

"Index.aspx" 是创建动态选项卡的主要位置。ID 为 "divTabs" 的 Div 是动态选项卡的 HTML 占位符,它是实现此功能所必需的唯一元素。选项卡的创建发生在 JavaScript 部分的 "$.ajax" 调用中。

  • 它首先对 "HomeController" 中的 "GetTabs" Action Method 进行一次 Ajax 调用。
  • 如果调用成功,"TabInfo" 对象列表将作为 Json 对象数组传递给 "$.ajax" 调用 "success" 参数对应的 "匿名函数"。
  • "GenerateTabs" 函数将使用每个 Json 对象中的信息来构建 jQuery 选项卡的 HTML UI 元素,并将它们附加到 ID 为 "divTabs" 的 Div 中。如果您想了解 jQuery 选项卡所需的 HTML UI 元素的详细信息,可以参考 此链接
  • 在 UI 元素构建并添加到 DOM 后,jQuery 调用 "$("#divTabs").tabs()" 将创建动态选项卡,而 "$tabs.tabs('select', 0)" 语句将激活第一个选项卡。

您可能需要注意的一点是,传递给每个选项卡项的 URL 不是来自 Json 对象的真正 "TabUrl"。选项卡项要加载的内容 URL 是 "IFrameContainer.aspx" 文件。

接下来,让我们看一下 "IFrameContainer.aspx"。

"IFrameContainer.aspx" 和 "IFrameWebLoader.aspx" 视图

"IFrameContainer.aspx" 实现如下:

<%@ Page Language="C#"
    Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
 
<html>
<head runat="server">
    <title></title>
</head>
<body>
    <iframe class="iframeInner"
        frameborder="0" scrolling="auto"
        src="<%= Url.Action("IFrameWebLoader", "Home",
            new {WebURL = ViewData["WebURL"]}) %>" />
</body>
</html>

"IFrameContainer.aspx" 文件是放置 "Iframe" 标签的地方。当用户单击一个选项卡项时,jQuery tabs 会进行一次 Ajax 调用以检索 "IFrameContainer.aspx" 页面的内容,然后将内容插入到 "Index.aspx" 页面中。如果将 "Iframe" 的 "src" 属性设置为 "TabUrl",则会加载 Json 对象中指定的所需网页。在本例中,我没有直接将 "Iframe" 的 "src" 属性设置为 "TabUrl"。而是将其设置为 "IFrameWebLoader.aspx",该页面实现如下:

<%@ Page Language="C#"
    Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link rel="stylesheet" type="text/css"
        href="<%= Url.Content("~/Styles/WebLoaderStyle.css") %>" />
 
    <script type="text/javascript"
        src="<%= Url.Content("~/Scripts/jquery-1.4.2.min.js") %>">
    </script>
    <script type="text/javascript">
        $(document).ready(function () {
            document.location.replace($("#WebURL").val());
        });
    </script>
</head>
<body>
 <input type="hidden" id="WebURL"
        value="<%= ViewData["WebURL"]%>" />
    <div id="WaitInfo">
  Page loading, please wait ...
    </div>
</body>
</html>

"IFrameWebLoader.aspx" 在一个隐藏字段中保存了 "TabUrl"。在 "$(document).ready" 事件中,我使用 JavaScript 读取隐藏字段并将页面重定向到 "TabUrl"。这个中间步骤不是绝对必需的。它只是为了在用户需要加载的网页加载时间较长时,向用户提供某种视觉反馈。我为此目的显示文本 "页面正在加载,请稍候..." 并将此页面的 "cursor" 设置为 "wait"。由于 "IFrameWebLoader.aspx" 页面非常小,因此开销应该最小。

在 Iframes 中承载外部网页

在许多情况下,使用 IFrames 承载网页是一个好主意。但如果您正在承载您无法控制的外部网页,则需要小心。我最近从一位同事那里得知,如果作者不希望有人在 IFrames 中承载他们的网页,他们可以通过一行 JavaScript 代码在其页面中放置一个 "Frame Buster"。

<script type="text/javascript">
  if (top != self) top.location.replace(self.location.href);
</script>

这个简单的 "Frame Buster" 非常有效。如果它发现网页是在框架中承载的,它就会破坏框架并接管整个 Web 浏览器窗口。虽然有些人研究过 "Framekiller",但它们似乎只能有限地 "杀死" Frame Busters。

如果您的目的是在 IFrames 中承载您自己的网页,您应该不会遇到任何问题,除非您想在 Web 应用程序中混合使用 "http/https"。在这种情况下,您的用户可能会看到一些警告消息。

运行应用程序

现在让我们运行我们的应用程序。在应用程序中,我添加了几个选项卡。一个选项卡加载 "Yahoo",其他选项卡加载一些 "Youtube" 视频。Yahoo 和 Youtube 都没有 "Frame Busters"。如果您单击一个选项卡,您会注意到 Json 对象中放置的网页已加载。下图显示了加载 Youtube 视频的选项卡。

RunApp.JPG

关注点

  • 本文介绍了一种使用 jQuery 和 Json 在 ASP.Net MVC 中动态生成承载 IFrames 的选项卡的方法。
  • Json 的内容可以在 MVC 控制器中配置,并通过 Ajax 调用加载到客户端。
  • jQuery 选项卡是通过 jQuery Plug-in 创建的。您可以参考 此链接 以获取更多详细信息。
  • 示例项目没有直接将 Iframe 的 src 属性设置为所需网页,而是转到一个中间页面,以便在加载所需网页时间较长时告知用户。
  • 如果您想在 IFrames 中承载外部网页,您应该注意 Frame Busters。
  • 希望您喜欢我的帖子,也希望这篇文章能以某种方式帮助您。

历史

  • 这是本文的第一个修订版。
© . All rights reserved.