具有页面加载优化和内容占位符的MVC部分呈现

时间:2010-09-27 02:19:42

标签: c# asp.net-mvc optimization

我一直在尝试组织我的观点来优化加载时间,方法是在头部使用css,在主体末端使用脚本。
为此,我创建了包含3个内容占位符的主页:样式,主要内容和脚本 通过(实现)目标,当我使用master呈现单个视图时,这可以整齐地将所有共享组件和特定页面组件整理到呈现页面中它们各自的位置。当我尝试渲染主 - 细节模型时,很难实现。

请考虑以下事项:

我有一个Master-Detail模型,说Order-OrderItems和订单的视图以及OrderItems的视图。努力做DRY而不是重复自己(doh!我刚刚做的就是:))我想在Order标题视图中部分呈现OrderItems列表视图并仍然实现正确的元素布局,即:具有任何特定的css被渲染到头部的内容占位符中,内容放入主要内容占位符和脚本到我的脚本内容占位符的底部。

我目前有一个令人讨厌的黑客,但想知道是否有更清洁的方法来做到这一点。

我当前的hack相当于带有where子句的sql cross join,我在订单视图的每个contentplaceholder中对orderitems视图进行部分呈现,并将该占位符的名称注入viewdata。在orderitems视图中,如果占位符名称不等于目标占位符,我返回并且只有css被渲染到css占位符等。要重新表达它,我在父级中渲染子项三次,而在孩子我为每次渲染返回内容的不同部分。

闻起来很有趣而不是非常优雅,因为孩子必须知道它正在被渲染等。

我的下一步想法是尝试拦截ViewPage的副本并使用SetRenderMethodDelegate控制渲染,只需在目标contentplaceholder控件上调用render,但此时此内容非常混乱。

有人能建议一种更好的方法来维护代码重用和最佳html输出吗?

一些示例代码:

    <%@ Master Language="C#" ... %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Master-Detail</title>
    <!--common styles-->
    <link type="text/css" href="my.css" rel="stylesheet" />
    <asp:ContentPlaceHolder ID="Styles" runat="server" ></asp:ContentPlaceHolder>
</head>
<body>
    <!--common markup-->    
    <h2>Master Markup</h2>
    <asp:ContentPlaceHolder ID="mainContent" runat="server"></asp:ContentPlaceHolder>

    <!--common scripts-->
    <script type="text/javascript" src="/scripts/my.js"></script>
    <asp:ContentPlaceHolder ID="Scripts" runat="server"></asp:ContentPlaceHolder>
</body>
</html>

订单视图

    <%@ Page Title="Order" Language="C#" MasterPageFile="~/Views/Shared/my.Master" ... %>

<asp:Content ContentPlaceHolderID="Styles" runat="server">
    <style type="text/css">
    /*order styles*/
    </style>
    <% 
        var partialContext = this.Html.GetViewContext("OrderDetails", "List", this.ViewData.Model.Items, this.ViewData);
        partialContext.RenderContentPlaceHolder("Styles");
    %>
</asp:Content>

<asp:Content ContentPlaceHolderID="MainContent" runat="server">
    <h3>Order Markup</h3>
    <% 
        var partialContext = this.Html.GetViewContext("OrderDetails", "List", this.ViewData.Model.Items, this.ViewData);
        partialContext.RenderContentPlaceHolder("MainContent");
    %>
</asp:Content>

<asp:Content ContentPlaceHolderID="Scripts" runat="server">
    <script type="text/javascript">
        /*order specific script*/
    </script>
     <%
         var partialContext = this.Html.GetViewContext("OrderDetails", "List", this.ViewData.Model.Items, this.ViewData);
         partialContext.RenderContentPlaceHolder("Scripts");
     %>
</asp:Content>

订单商品查看:

    <%@ Page Title="OrderItems" Language="C#" MasterPageFile="my.aspx" ... %>

<asp:Content ID="Content2" ContentPlaceHolderID="Styles" runat="server">
    <% if (ViewData["placeHolderName"] != null && ViewData["placeHolderName"].ToString().ToLower() != "styles")
           return; %>
    <style type="text/css">
       /*OrderItems style*/
    </style>
</asp:Content>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <% if (ViewData["placeHolderName"] != null && ViewData["placeHolderName"].ToString().ToLower() != "maincontent")
           return; %>
    <h4>Order Items MarkUp</h4>
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="Scripts" runat="server">
    <% if (ViewData["placeHolderName"] != null && ViewData["placeHolderName"].ToString().ToLower() != "scripts")
           return; %>
    <script type="text/javascript">
        /*Order Items script*/
    </script>
</asp:Content>

哪里有几种扩展方法:

        public static ViewContext GetViewContext(this HtmlHelper htmlHelper, String controller, String viewName, Object model, ViewDataDictionary viewData)
    {
        var routeData = new System.Web.Routing.RouteData();
        routeData.Values["controller"] = controller;

        var controllerContext = new ControllerContext(htmlHelper.ViewContext.HttpContext, routeData, htmlHelper.ViewContext.Controller);

        var viewEngineResult = ViewEngines.Engines.FindView(controllerContext, viewName, "Partial");

        var viewData2 = new ViewDataDictionary(viewData);
        viewData2.Model = model;

        var viewContext = new ViewContext(controllerContext, viewEngineResult.View, viewData2, htmlHelper.ViewContext.TempData, htmlHelper.ViewContext.Writer);

        return viewContext;
    }

    public static void RenderContentPlaceHolder(this ViewContext context, String placeHolderName)
    {
        context.ViewData["placeHolderName"] = placeHolderName;
        context.View.Render(context, context.Writer);
        context.ViewData.Remove("placeHolderName");
    }

1 个答案:

答案 0 :(得分:1)

看看前面提到过的类似问题:

How can I include css files from an MVC partial control?

特别是在接受的答案中提供的链接非常有趣:

http://www.codeproject.com/Articles/38542/Include-Stylesheets-and-Scripts-From-A-WebControl-.aspx

编辑:您可以在此处找到为MVC 2更新的同一作者的另一篇博文:http://somewebguy.wordpress.com/2010/04/06/adding-stylesheets-scripts-in-asp-net-mvc2/