【问题标题】:Setting masterName on MVC view causes error when calling RenderAction在 MVC 视图上设置 masterName 会导致调用 RenderAction 时出错
【发布时间】:2011-03-03 02:06:22
【问题描述】:

我有一个使用 RenderAction 调用视图的 Masterpage (site.master)。目前视图返回“hello world”。

site.master:

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>

<html>
<head id="Head1" runat="server">
   <title><asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" /></title>
   <asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server" />
</head>

<body>
    <% Html.RenderAction("Test", "Charts"); %>

    <asp:ContentPlaceHolder ID="ContentPlaceHolder3" runat="server" >
      <p>site.master</p>
    </asp:ContentPlaceHolder>

    <asp:ContentPlaceHolder ID="ContentPlaceHolder4" runat="server" />  
</body>
</html>

Test.aspx:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

hello world!

ChartsController.cs:

public ActionResult Test()
{
    return View();
}

如果我更新视图以明确传递母版页的名称,我在调用 RenderAction 时会收到错误。

ChartsController.cs:

public ActionResult Test()
{
    return View(null, "site");
}

错误:

内容控件必须是内容页或引用母版页的嵌套母版页中的顶级控件。

Stack Trace:

[HttpException (0x80004005): Content controls have to be top-level controls in a content page or a nested master page that references a master page.]
   System.Web.UI.MasterPage.CreateMaster(TemplateControl owner, HttpContext context, VirtualPath masterPageFile, IDictionary contentTemplateCollection) +8857854
   System.Web.UI.Page.get_Master() +54
   System.Web.UI.Page.ApplyMasterPage() +15
   System.Web.UI.Page.PerformPreInit() +45
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +328

如何设置我希望视图使用的母版页?最终,我将使用自定义 ViewEngine(通过覆盖 VirtualPathProviderViewEngine.FindView)动态设置 Masterpage。

if ( String.IsNullOrEmpty(masterName) ){ masterName = "site"; }

当我在 ViewEngine 中设置 masterName 属性,然后从 site.master 调用 RenderAction 时,我得到与在 Action 中设置 masterName 属性时相同的错误。

我正在使用:
视觉工作室 2010
MVC 3
IIS Express

已编辑:添加了完整的 site.master 标记

【问题讨论】:

  • 您可以标记您的母版页吗?如果视图对于每个母版页都没有相同的内容占位符,则您的发送将会发生

标签: asp.net-mvc-3 master-pages viewengine renderaction


【解决方案1】:

子类ViewPage&lt;T&gt; 并覆盖OnPreInit() 事件。在您的覆盖中,

protected override void OnPreInit(EventArgs e)
{
    this.MasterLocation = GetMasterLocation();
    base.OnPreInit(e);
}

GetMasterLocation() 方法应该获取视图的文件名(以“~/”开头)。

错误来自MasterPage中的CreateMaster方法,抛出它的代码是:

if (masterPageFile == null)
{
    if ((contentTemplateCollection != null) && (contentTemplateCollection.Count > 0))
    {
        throw new HttpException(SR.GetString("Content_only_allowed_in_content_page"));
    }
    return null;
}

因此,MasterPage 不存在且内容模板集合具有模板,因此页面会引发异常。按照上述说明,将以编程方式设置母版页的位置(处理到虚拟路径,即变量 masterPageFile)

【讨论】:

    【解决方案2】:

    我已经想出了一个解决方案,并且至少对我的问题的原因有部分答案/理解。

    如果我是正确的,问题是我试图在没有/不需要母版页的视图上设置母版页。我认为结果是我设置了母版页的路径,即使该母版页存在,视图也没有预料到它并通过错误。

    当我更新视图以使用母版页时,我能够将母版页的名称直接传递给视图而不会出错。

    Test.aspx:

    <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Charts.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
    
    <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
        hello world!
    </asp:Content>
    

    我在自定义 ViewEngine 中解决此问题的方法是检查当前 View 是否为 ChildAction。

    if (String.IsNullOrEmpty(masterName) && !controllerContext.IsChildAction)
    {
        masterName = "site";
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 2012-10-22
      • 1970-01-01
      相关资源
      最近更新 更多