Tengo un sitio MVC3 que usa Razor como motor de visualización. Quiero que mi sitio sea personalizable. La mayoría de las máscaras posibles son lo suficientemente similares como para derivar de un diseño maestro compartido.
Por lo tanto, estoy considerando este diseño:
Sin embargo, me gustaría ser capaz de llamar RenderSection
en la capa inferior, _Common.cshtml
y tienen que rinde una sección que se define en la capa superior, Detail.cshtml
. Esto no funciona: RenderSection
aparentemente solo renderiza las secciones que están definidas en la siguiente capa.
Por supuesto, puedo definir cada sección en cada skin. Por ejemplo, si _Common
necesita llamar RenderSection("hd")
a una sección definida en Detail
, simplemente coloco esto en cada uno _Skin
y funciona:
@section hd {
@RenderSection("hd")
}
Esto da como resultado cierta duplicación de código (ya que ahora cada máscara debe tener la misma sección) y, en general, se siente desordenado. Todavía soy nuevo en Razor y parece que me estoy perdiendo algo obvio.
Al depurar, puedo ver la lista completa de secciones definidas en WebViewPage.SectionWritersStack. Si pudiera decirle a RenderSection que revise toda la lista antes de rendirme, encontraría la sección que necesito. Por desgracia, SectionWritersStack no es público.
Alternativamente, si pudiera acceder a la jerarquía de páginas de diseño e intentar ejecutar RenderSection en cada contexto diferente, podría ubicar la sección que necesito. Probablemente me esté perdiendo algo, pero no veo ninguna forma de hacer esto.
¿Hay alguna forma de lograr este objetivo, además del método que ya describí?
fuente
@helper ForwardSection( string section ) { if (IsSectionDefined(section)) { DefineSection(section, () => Write(RenderSection(section))); } }
¿Esto haría el trabajo?
fuente
No estoy seguro de si esto es posible en MVC 3, pero en MVC 5 puedo hacerlo con éxito usando el siguiente truco:
En
~/Views/Shared/_Common.cshtml
escriba su código HTML común como:<!DOCTYPE html> <html lang="fa"> <head> <title>Skinnable - @ViewBag.Title</title> </head> <body> @RenderBody() </body> </html>
En
~/Views/_ViewStart.cshtml
:@{ Layout = "~/Views/Shared/_Common.cshtml"; }
Ahora todo lo que tienes que hacer es usar
_Common.cshtml
comoLayout
para todas las máscaras. Por ejemplo, en~/Views/Shared/Skin1.cshtml
:@{ Layout = "~/Views/Shared/_Common.cshtml"; } <p>Something specific to Skin1</p> @RenderBody()
Ahora puede configurar la máscara como su diseño en el controlador o la vista según sus criterios. Por ejemplo:
public ActionResult Index() { //.... if (user.SelectedSkin == Skins.Skin1) return View("ViewName", "Skin1", model); }
Si ejecuta el código anterior, debería obtener una página HTML con el contenido
Skin1.cshtml
y_Common.cshtml
En resumen, establecerá el diseño de la página de diseño (aspecto).
fuente
No estoy seguro de si esto le ayudará, pero escribí algunos métodos de extensión para ayudar a "burbujear" las secciones desde los parciales, que también deberían funcionar para diseños anidados.
Inyectar contenido en secciones específicas desde una vista parcial ASP.NET MVC 3 con Razor View Engine
Declarar en diseño secundario / vista / parcial
Render en cualquier padre
Consulte el enlace de respuesta para obtener más casos de uso, como representar solo un bloque retrasado incluso si se declara en una vista repetida, representar bloques retrasados específicos, etc.
fuente