Установка masterName в представлении MVC вызывает ошибку при вызове RenderAction

У меня есть Masterpage (site.master), которая вызывает View с помощью RenderAction. В настоящий момент View возвращает «привет, мир».

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();
}

Если я обновляю View, чтобы явно передать имя Masterpage, я получаю сообщение об ошибке при вызове 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"; }

Когда я устанавливаю свойство masterName в моем ViewEngine, а затем вызываю RenderAction из site.master, я получаю ту же ошибку, что и при установке свойства masterName в Action.

Я использую:
Visual Studio 2010
MVC 3
IIS Express

отредактировано: добавлена ​​полная разметка site.master


person codingintherain    schedule 03.03.2011    source источник
comment
может вы должны разметить вашу главную страницу (ы)? Если представление не имеет одинаковых заполнителей содержимого для каждой отправляемой вами главной страницы, это произойдет.   -  person hunter    schedule 03.03.2011


Ответы (2)


Создайте подкласс 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)

person smartcaveman    schedule 03.03.2011

Я нашел решение и, по крайней мере, частичный ответ / понимание причины моей проблемы.

Если я прав, проблема в том, что я пытаюсь установить Masterpage на представление, которое не имело / не нуждалось в Masterpage. Я думаю, что результатом было то, что я устанавливал путь к мастер-странице, и хотя эта мастер-страница существует, View не ожидал этого и из-за ошибки.

Когда я обновил представление для использования мастер-страницы, я смог передать имя мастер-страницы непосредственно в представление без ошибок.

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";
}
person codingintherain    schedule 03.03.2011