2010-11-02 25 views
4

J'ai beaucoup de vues avec beaucoup de contenu sur mon site ASP.NET MVC 2. Ceux-ci contiennent plusieurs modèles HTML qui se reproduisent. Lors de l'utilisation de formulaires Web ASP.NET, une classe dérivée de WebControl peut encapsuler ces modèles. Je voudrais quelques conseils sur la bonne approche pour ce problème avec MVC.Comment faire pour résumer des extraits courants de balisage avec ASP.NET MVC

Explication détaillée

modèles peu comme le donjon balisage HTML suivant se produire tout au long de ces vues. Le balisage rend dans un endroit isolé une boîte de contenu:

<div class="top container"> 
    <div class="header"> 
     <p>The title</p> 
     <em>(and a small note)</em> 
    </div> 
    <div class="simpleBox rounded"> 
     <p>This is content.</p> 
     <p><strong>Some more content</strong></p> 
    </div> 
</div> 

Ceci est un exemple trivial, mais il y a des motifs récurrents plus complexes. Dans ASP.NET WebForms j'aurais abstraire tel code dans un WebControl (disons que je l'ai nommé BoxControl), d'être mis sur une page comme celle-ci:

<foo:BoxControl runat="server"> 
    <Header>The title</Header> 
    <Note>(and a small note)</Header> 
    <Content> 
    <p>This is content.</p> 
    <p><strong>Some more content</strong></p> 
    </Content> 
</foo:BoxControl> 

Cette abstraction permet d'adapter facilement la manière la boîte est construite sur tout le site, en modifiant simplement la source BoxControl. Il conserve également le contenu HTML statique de manière cohérente dans la page de visualisation, même en combinant plusieurs BoxControls sur une page. Un autre avantage est que le code HTML utilisé comme contenu est reconnu par l'EDI, fournissant ainsi une coloration syntaxique/vérification. Pour ma compréhension, les WebControls sont déconseillés dans ASP.NET MVC. Au lieu d'un WebControl, je pourrais accomplir l'abstraction avec une vue partielle. Une telle vision serait alors incluse dans une vue page comme suit:

<%= Html.Partial("BoxControl", new { 
    Header="The Title", 
    Note="(and a small note)", 
    Content="<p>This is content.</p><p><strong>Some more content</strong></p>"}); 
%> 

Ce n'est pas idéal, car le paramètre « Contenu » pourrait devenir très long, et l'IDE ne traite pas comme HTML lorsqu'il est passé de cette façon .

Solutions Considéré comme ViewModels fortement typées peuvent être transmis à l'appel Html.Partial au lieu des longs paramètres indiqués ci-dessus. Mais alors je devrais extraire le contenu d'un autre endroit (un CMS ou un fichier de ressources). Je voudrais que le contenu soit contenu dans la page de vue.

J'ai également considéré the solution proposed by Jeffrey Palermo, mais cela signifierait beaucoup de fichiers supplémentaires dispersés dans le projet. Je souhaite que le contenu textuel d'une vue soit limité à un seul fichier.

Ne devrais-je pas supprimer le balisage? Ou y a-t-il peut-être une approche, adaptée à MVC, que je néglige ici? Quel est l'inconvénient de «pécher» en utilisant un WebControl?

+0

Je relis votre que stion et je pense que @ RPM1984 est probablement le meilleur moyen d'y aller –

Répondre

1

Après avoir examiné les réponses et l'exécution d'une expérience, je suis enclin à adhérer à la MVC pur approchez et dupliquez du code de présentation dans les pages de vue. J'aimerais préciser les raisons de cette décision.

Vue partielle Lorsque vous utilisez une vue partielle, le contenu de la boîte doit être passée en vue de modèle, ce qui rend la vue page lisible moins par rapport à déclarer le contenu HTML sur place. Souvenez-vous que le contenu ne provient pas d'un système de gestion de contenu, ce qui signifie que vous devez remplir le modèle View avec HTML dans un contrôleur ou définir une variable locale dans la page View. Ces deux méthodes ne parviennent pas à tirer parti des fonctionnalités IDE pour traiter le HTML.

WebControl D'autre part, une classe dérivée WebControl-est découragée et tourne également avoir quelques problèmes pratiques. Le problème principal que le style déclaratif et hiérarchique des pages ASP.NET .aspx traditionnelles ne correspond tout simplement pas au style procédural des pages d'affichage MVC.NET. Vous devez choisir soit une approche traditionnelle complète, soit aller complètement MVC. Pour illustrer cela, le problème le plus important dans mon implémentation expérimentale était celui de portée variable: lors de l'itération d'une liste de produits, le MVC-way doit utiliser une boucle foreach, mais cela introduit une variable locale qui ne sera pas disponible dans le cadre du WebControl. L'approche ASP.NET traditionnelle serait d'utiliser un répéteur au lieu de foreach. Il semble que ce soit une pente glissante pour utiliser n'importe quel contrôle ASP.NET traditionnel, parce que je pense que vous aurez bientôt besoin de combiner de plus en plus d'entre eux pour faire le travail.

Plain HTML En renonçant à l'abstraction, il vous reste un code de présentation en double. C'est contre DRY, mais produit un code très lisible.

1

Eh bien, vous ne rendrait pas la partie comme ça, passer un ViewModel, comme celui-ci fortement typé:

<%= Html.RenderPartial("BoxControl", contentModel) %> 

contentModel est le ViewModel (juste un mécanisme de stockage POCO comme pour votre point de vue), auquel la vue partielle fortement typée se lierait.

Ainsi, vous pouvez le faire dans votre vue partielle:

<h1><%: Model.Header %></h1> 
<p><%: Model.Content %></p> 

etc etc

+0

Merci pour votre réponse, c'est en effet une alternative à ce que je considérais. Cependant, je suis à la recherche d'un moyen qui conserve le contenu actuel (assez statique) de la page View. J'ai édité la question pour clarifier ceci. –

+0

je ne suis pas sûr de ce que vous voulez dire pourquoi "conserve le contenu réel (assez statique) dans la page de visualisation." quel est le point du contrôle partiel/utilisateur alors? quelle information/logique/code est réutilisé? – RPM1984

+0

Je voudrais que la page de vue contienne du contenu organisé sans balisage de présentation. La présentation provient idéalement des fichiers CSS externes, mais pour les mises en page complexes, les fichiers CSS seuls ne suffisent pas toujours et il faut du HTML non content (présentation). C'est le cas avec une mise en page complexe de «boîte» que j'utilise fréquemment dans mes Pages de Vue. Je voudrais abstraire cette présentation HTML, de sorte que lorsque je décide de changer l'apparence de la boîte, je n'ai pas besoin de passer par beaucoup de vues pour changer le balisage. Pour répondre à votre question: je veux réutiliser le HTML récurrent de présentation non-content. –

0

Il ne ressemble pas à webforms a beaucoup moins html pour moi, il semble plus comme un mouvement latéral.L'utilisation d'un partiel dans MVC peut le rendre plus propre mais le balisage html dont vous avez besoin sera toujours là, à un endroit ou à un autre. Si c'est surtout le html supplémentaire qui vous dérange, vous pouvez jeter un coup d'oeil au moteur de vue NHaml ou consultez le code the haml website.

Je suis pas un expert, mais Haml le code html ne semble beaucoup plus propre ...

.top container 
    .header 
     %p 
     The title 
     %em 
     (and a small note) 
    .simpleBox rounded 
     %p 
     This is content. 
     %p 
     Some more content 
+0

remercie Justin, une approche intéressante. haml ne fait que comprimer le balisage, il ne l'extrait pas ailleurs. Ce n'est pas grave pour moi si c'est plus ou moins de code, seulement si la maintenance et la lisibilité sont améliorées. –

4

Il existe une solution à ce problème, bien que la manière d'y arriver soit un peu plus cluteuse que d'autres frameworks comme Ruby on Rails.

Je l'ai utilisé cette méthode pour créer un balisage pour la syntaxe du groupe de contrôle de Twitter Bootstrap qui ressemble à ceci:

<div class="control-group"> 
    <label class="control-label">[Label text here]</label> 
    <div class="controls"> 
    [Arbitrary markup here] 
    </div> 
</div> 

Voilà comment:

1) Créer un modèle pour l'extrait de code de balisage commun.Le modèle devrait écrire un balisage sur la construction et à nouveau sur Éliminez:

using System; 
using System.Web.Mvc; 

namespace My.Name.Space 
{ 
    public class ControlGroup : IDisposable 
    { 
    private readonly ViewContext m_viewContext; 
    private readonly TagBuilder m_controlGroup; 
    private readonly TagBuilder m_controlsDiv; 

    public ControlGroup(ViewContext viewContext, string labelText) 
    { 
     m_viewContext = viewContext; 
     /* 
     * <div class="control-group"> 
     * <label class="control-label">Label</label> 
     * <div class="controls"> 
     * input(s) 
     * </div> 
     * </div> 
     */ 

     m_controlGroup = new TagBuilder("div"); 
     m_controlGroup.AddCssClass("control-group"); 
     m_viewContext.Writer.Write(m_controlGroup.ToString(TagRenderMode.StartTag)); 

     if (labelText != null) 
     { 
     var label = new TagBuilder("label"); 
     label.AddCssClass("control-label"); 
     label.InnerHtml = labelText; 
     m_viewContext.Writer.Write(label.ToString()); 
     } 

     m_controlsDiv = new TagBuilder("div"); 
     m_controlsDiv.AddCssClass("controls"); 
     m_viewContext.Writer.Write(m_controlsDiv.ToString(TagRenderMode.StartTag)); 

    } 

    public void Dispose() 
    { 
     m_viewContext.Writer.Write(m_controlsDiv.ToString(TagRenderMode.EndTag)); 
     m_viewContext.Writer.Write(m_controlGroup.ToString(TagRenderMode.EndTag)); 
    } 
    } 
} 

2) Créer un assistant astucieux Html

using System.Collections.Generic; 
using System.Linq; 
using System.Web.Mvc; 

using My.Name.Space 

namespace Some.Name.Space 
{ 
    public static class FormsHelper 
    { 
    public static ControlGroup ControlGroup(this HtmlHelper helper, string labelText) 
    { 
     return new ControlGroup(helper.ViewContext, labelText); 
    } 
    } 
} 

3) Utilisez dans la vue (code Razor)

@using (Html.ControlGroup("My label")) 
{ 
    <input type="text" /> 
    <p>Arbitrary markup</p> 
    <input type="text" name="moreInputFields" /> 
} 

Ceci est également la façon dont MVC rend un formulaire avec la méthode Html.BeginForm