У меня есть сайт MVC3, использующий Razor в качестве движка просмотра. Я хочу, чтобы мой сайт можно было изменять. Большинство возможных скинов достаточно похожи, чтобы их можно было извлечь из общего главного макета.
Поэтому рассматриваю такую конструкцию:
Тем не менее, я хотел бы иметь возможность вызвать RenderSection
в нижнем слое, _Common.cshtml
и иметь его вынести раздел, определенный в верхнем слое, Detail.cshtml
. Это не работает: по- RenderSection
видимому, визуализируются только те разделы, которые определены на следующем уровне.
Конечно, я могу определить каждую секцию в каждом скине. Например, если _Common
нужно вызвать RenderSection("hd")
раздел, определенный в Detail
, я просто помещаю его в каждый, _Skin
и он работает:
@section hd {
@RenderSection("hd")
}
Это приводит к некоторому дублированию кода (поскольку каждый скин теперь должен иметь один и тот же раздел) и, как правило, кажется беспорядочным. Я все еще новичок в Razor, и мне кажется, что я упускаю что-то очевидное.
При отладке я могу видеть полный список определенных разделов в WebViewPage.SectionWritersStack. Если бы я мог просто сказать RenderSection просмотреть весь список, прежде чем сдаться, он бы нашел нужный мне раздел. Увы, SectionWritersStack не является публичным.
В качестве альтернативы, если бы я мог получить доступ к иерархии страниц макета и попытаться выполнить RenderSection в каждом другом контексте, я мог бы найти нужный мне раздел. Я, наверное, что-то упускаю, но не вижу способа сделать это.
Есть ли способ достичь этой цели, кроме метода, который я уже описал?
источник
@helper ForwardSection( string section ) { if (IsSectionDefined(section)) { DefineSection(section, () => Write(RenderSection(section))); } }
Сработает ли это?
источник
Я не уверен, возможно ли это в MVC 3, но в MVC 5 я могу успешно сделать это, используя следующий трюк:
В
~/Views/Shared/_Common.cshtml
записи ваш общий HTML - код , как:<!DOCTYPE html> <html lang="fa"> <head> <title>Skinnable - @ViewBag.Title</title> </head> <body> @RenderBody() </body> </html>
В
~/Views/_ViewStart.cshtml
:@{ Layout = "~/Views/Shared/_Common.cshtml"; }
Теперь все, что вам нужно сделать, это использовать в
_Common.cshtml
качестве элементаLayout
для всех скинов. Например, в~/Views/Shared/Skin1.cshtml
:@{ Layout = "~/Views/Shared/_Common.cshtml"; } <p>Something specific to Skin1</p> @RenderBody()
Теперь вы можете установить скин в качестве макета в контроллере или в представлении в зависимости от ваших критериев. Например:
public ActionResult Index() { //.... if (user.SelectedSkin == Skins.Skin1) return View("ViewName", "Skin1", model); }
Если вы запустите приведенный выше код, вы должны получить HTML-страницу с содержимым
Skin1.cshtml
и_Common.cshtml
Короче говоря, вы установите макет для страницы макета (скина).
источник
Не уверен, что это поможет вам, но я написал несколько методов расширения, которые помогают «всплывать» разделы внутри частичных файлов, которые также должны работать для вложенных макетов.
Внедрение содержимого в определенные разделы из частичного представления ASP.NET MVC 3 с Razor View Engine
Объявить в дочернем макете / представлении / частичном
Рендеринг в любом родителе
См. Ссылку для ответа на другие варианты использования, например, рендеринг только одного отложенного блока, даже если он объявлен в повторяющемся представлении, рендеринг определенных отложенных блоков и т. Д.
источник