我一直在試圖組織我的意見,以優化加載時間,通過在正文的頭部和腳本的css結束。
爲此,我創建了具有3個內容佔位符的主頁:styles,maincontent和scripts。
隨着(實現)的目標,當我與主人渲染一個單一的視圖整齊地可以整理所有的共享組件和特定頁面組件到他們各自的地方在渲染頁面。當我嘗試渲染一個主 - 細節模型時,這很困難。MVC部分呈現與頁面加載優化和內容佔位符
考慮以下幾點:
我有一個主從模型說,訂單的OrderItems和視圖訂單和視圖的的OrderItems。爲了做到DRY而不是重複自己(doh!我只是做了正確的:))我想部分呈現Order Order視圖中的OrderItems列表視圖,並仍然實現正確的元素佈局,即:具有任何特定css被渲染到頭部的內容佔位符中,內容到主要內容佔位符中,並且腳本到腳本內容佔位符的底部。
我現在有一個討厭的黑客,但想知道是否有更乾淨的方式來做到這一點。
我目前的hack相當於一個使用where子句的sql交叉連接,因爲我在order view的每個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");
}