Dispositifs nesteds de razor avec des sections en cascade

J’ai un site MVC3 utilisant Razor comme moteur de vue. Je veux que mon site soit pelable. La plupart des habillages possibles sont suffisamment similaires pour pouvoir dériver d’une mise en page maître partagée.

Par conséquent, je considère cette conception:

Diagramme de vue planifiée

Cependant, j’aimerais pouvoir appeler RenderSection dans le calque inférieur, _Common.cshtml , et le rendre dans une section définie dans le calque supérieur, Detail.cshtml . Cela ne fonctionne pas: RenderSection ne rend apparemment que les sections définies dans la couche suivante.

Bien sûr, je peux définir chaque section dans chaque peau. Par exemple, si _Common doit appeler RenderSection("hd") pour une section définie en Detail , je le place dans chaque _Skin et cela fonctionne:

 @section hd { @RenderSection("hd") } 

Cela entraîne une certaine duplication du code (puisque chaque skin doit maintenant avoir cette même section) et se sent généralement en désordre. Je suis encore nouveau chez Razor, et il semble que je puisse manquer quelque chose d’évident.

Lors du débogage, je peux voir la liste complète des sections définies de WebViewPage.SectionWritersStack. Si je pouvais simplement dire à RenderSection de parcourir toute la liste avant d’abandonner, il trouverait la section dont j’ai besoin. Hélas, SectionWritersStack est non-public.

Par ailleurs, si je pouvais accéder à la hiérarchie des pages de mise en page et tenter d’exécuter RenderSection dans chaque contexte, je pourrais localiser la section dont j’ai besoin. Je manque probablement quelque chose, mais je ne vois aucun moyen de le faire.

Y a-t-il un moyen d’atteindre cet objective, autre que la méthode que j’ai déjà décrite?

Cela n’est en fait pas possible aujourd’hui en utilisant l’API publique (autre que l’approche de redéfinition de section). Vous pourriez avoir de la chance en utilisant la reflection privée, mais c’est bien sûr une approche fragile. Nous chercherons à faciliter ce scénario dans la prochaine version de Razor.

En attendant, voici quelques articles de blog que j’ai écrits sur le sujet:

 @helper ForwardSection( ssortingng section ) { if (IsSectionDefined(section)) { DefineSection(section, () => Write(RenderSection(section))); } } 

Est-ce que cela ferait le travail?

Je ne suis pas sûr que cela soit possible dans MVC 3 mais dans MVC 5, je suis capable de faire cela en utilisant l’astuce suivante:

Dans ~/Views/Shared/_Common.cshtml écrivez votre code HTML commun tel que:

 < !DOCTYPE html>   Skinnable - @ViewBag.Title   @RenderBody()   

Dans ~/Views/_ViewStart.cshtml :

 @{ Layout = "~/Views/Shared/_Common.cshtml"; } 

Il ne vous rest plus qu’à utiliser le _Common.cshtml pour tous les skins. Par exemple, dans ~/Views/Shared/Skin1.cshtml :

 @{ Layout = "~/Views/Shared/_Common.cshtml"; } 

Something specific to Skin1

@RenderBody()

Maintenant, vous pouvez définir la peau comme votre mise en page dans le contrôleur ou la vue en fonction de vos critères. Par exemple:

  public ActionResult Index() { //.... if (user.SelectedSkin == Skins.Skin1) return View("ViewName", "Skin1", model); } 

Si vous exécutez le code ci-dessus, vous devriez obtenir une page HTML contenant à la fois le contenu de Skin1.cshtml et _Common.cshtml

En bref, vous allez définir la mise en page pour la page de mise en page (skin).

Je ne suis pas sûr que cela vous aidera, mais j’ai écrit quelques méthodes d’extension pour aider à “faire éclater” des sections à partir de partiels, ce qui devrait également fonctionner pour des mises en page nestedes.

Injection de contenu dans des sections spécifiques à partir d’une vue partielle ASP.NET MVC 3 avec Razor View Engine

Déclarez dans la mise en page enfant / vue / partielle

 @using (Html.Delayed()) { show me multiple times, @Model.Whatever } 

Rendre dans n’importe quel parent

 @Html.RenderDelayed(); 

Voir le lien de réponse pour plus de cas d’utilisation, comme le rendu d’un seul bloc retardé même s’il est déclaré dans une vue répétitive, le rendu de blocs retardés spécifiques, etc.