0

RenderActionを使用してビューを呼び出すマスターページ(site.master)があります。現時点では、ビューは「helloworld」を返します。

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をオーバーライドすることにより)マスターページを動的に設定します。

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

ViewEngineでmasterNameプロパティを設定してから、site.masterからRenderActionを呼び出すと、ActionでmasterNameプロパティを設定した場合と同じエラーが発生します。

使用しているもの:
Visual Studio 2010
MVC 3
IIS Express

編集:完全なsite.masterマークアップを追加

4

2 に答える 2

0

イベントをサブクラスViewPage<T>化してオーバーライドしますOnPreInit()。オーバーライドでは、

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

メソッドは、ビューのGetMasterLocation()ファイル名( ""で始まる~/)を取得する必要があります。

エラーはのCreateMasterメソッドから発生しMasterPage、それをスローするコードは次のとおりです。

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

したがって、MasterPageは存在せず、コンテンツテンプレートコレクションにはテンプレートがあるため、ページは例外をスローします。上記の手順に従うと、マスターページの場所がプログラムで設定されます(変数である仮想パスに処理されますmasterPageFile) 。

于 2011-03-03T02:59:52.733 に答える
0

私は自分の問題の原因に対する解決策と少なくとも部分的な答え/理解を考え出しました。

私が正しければ、問題は、マスターページを持っていない/必要としないビューにマスターページを設定しようとしていることです。その結果、マスターページへのパスを設定していたと思います。マスターページが存在していても、ビューはそれを予期していなかったため、エラーが発生しました。

マスターページを使用するようにビューを更新したとき、エラーなしでマスターページの名前をビューに直接渡すことができました。

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でこれを解決する方法は、現在のビューがChildActionであるかどうかを確認することでした。

if (String.IsNullOrEmpty(masterName) && !controllerContext.IsChildAction)
{
    masterName = "site";
}
于 2011-03-03T20:52:16.763 に答える