Как использовать "RenderBody()" в частичном представлении, когда частичное представление совместно используется на страницах макета?
Вот точный сценарий в моем приложении ASP.NET MVC:
Есть две страницы макета, которые совершенно идентичны друг другу. Но у одного в теге "" есть связанные с углом атрибуты, а у другого - неугловое расположение. Чтобы избежать дублирования разметки в обоих файлах макета бритвы, я подумал создать частичное представление и поделиться им на страницах макета.
Ниже приведен частичный вид (бритва), я назвал его "_LayoutPartial":
_LayoutPartial.cshtml
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
Приведенное выше частичное представление используется совместно в "_Layout.cshtml" и "_AngularLayout.cshtml", как указано ниже:
_Layout.cshtml
<body>
@Html.Partial("_LayoutPartial")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
_AngularLayout.cshtml
<body ng-app="myAngularLab">
@Html.Partial("_LayoutPartial")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
Когда я пытаюсь запустить приложение MVC, я получаю следующую ошибку:
Файл "~/Views/Shared/_LayoutPartial.cshtml" не может быть запрошен напрямую, потому что он вызывает метод "RenderBody".
Сообщение об ошибке очень очевидно, и кажется, что мы можем использовать метод RenderBody только на главной странице, и нигде больше. Но мне интересно знать, как мы можем получить две идентичные страницы макета (с небольшими отличиями, как показано в примере), написав общий код вместо хранения дублирующего кода на обеих страницах макета?
2 ответа
Я думаю, что вам нужно использовать "вложенный макет", поместив одну страницу макета в качестве "главной страницы" для других макетов, аналогично аналогу веб-форм:
_BaseLayout.cshtml
<html>
<head>
<!-- other header tags (link, meta, title etc.) -->
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
<!-- JS & CSS includes if available -->
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<!-- other elements -->
</div>
<div class="container body-content">
@RenderBody()
<!-- other elements -->
</div>
@RenderSection("scripts", required: false)
</body>
</html>
_Layout.cshtml
@{ Layout = "~/Views/Shared/_BaseLayout.cshtml"; } // put reference to base layout here
<div>
<!-- Non-Angular layout -->
@RenderBody()
</div>
_AngularLayout.cshtml
@{ Layout = "~/Views/Shared/_BaseLayout.cshtml"; } // put reference to base layout here
<div ng-app="myAngularLab">
<!-- Angular layout -->
@RenderBody()
</div>
Преимущества использования "вложенного макета":
Устраняет необходимость повторения
@Styles.Render
&@Scripts.Render
также для@RenderSection
(они вставляются автоматически для каждой страницы, ссылающейся на базовый макет).Устраняет необходимость использовать более одного
body
тег, просто замените наdiv
тег для просмотра содержимого страницы.
Файл "X" не может быть запрошен напрямую, потому что он вызывает метод "RenderBody", несомненно, произошел из Html.Partial
который вызывается непосредственно из дочерних макетов, где макет страницы с RenderBody
метод не может быть запрошен напрямую как шаблон.
Если вы хотите установить макет по умолчанию для вложенного макета, поместите один из ссылок на дочерний макет в _ViewStart.cshtml
:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Еще одно примечание: частичные представления предназначены для использования на страницах просмотра, а не на страницах макета. Страницы макета специально используются в качестве заполнителя для страниц просмотра, а не для прямого доступа к методам действий.
Попробуйте это в _Layout.cshtml:
<body>
@Html.Partial("_LayoutPartial")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
</body>
и удалите @RenderBody()
от _LayoutPartial.cshtml
,
@RenderBody()
обычно используется на страницах макета, он отображает часть страницы содержимого, которая не находится в названном разделе.
Надеюсь, что это полезно:)