ASP.NET MVC 3 - Modello di visualizzazione parziale vs modello di editor


303

Quindi, il titolo dovrebbe parlare da solo.

Per creare componenti riutilizzabili in ASP.NET MVC, abbiamo 3 opzioni (potrebbero essere altri che non ho menzionato):

Vista parziale:

@Html.Partial(Model.Foo, "SomePartial")

Modello di editor personalizzato:

@Html.EditorFor(model => model.Foo)

Modello di visualizzazione personalizzato:

@Html.DisplayFor(model => model.Foo)

In termini di visualizzazione / HTML effettivi, tutte e tre le implementazioni sono identiche:

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

Quindi, la mia domanda è: quando / come decidi quale dei tre usare?

Quello che sto davvero cercando è un elenco di domande da porsi prima di crearne uno, per il quale è possibile utilizzare le risposte per decidere quale modello utilizzare.

Ecco le 2 cose che ho trovato meglio con EditorFor / DisplayFor:

  1. Rispettano le gerarchie dei modelli durante il rendering degli helper HTML (ad es. Se sul modello "Foo" è presente un oggetto "Bar", gli elementi HTML per "Bar" verranno visualizzati con "Foo.Bar.ElementName", mentre un parziale avrà " ElementName ").

  2. Più robusto, ad esempio se List<T>nel ViewModel avevi qualcosa di simile, puoi usarlo @Html.DisplayFor(model => model.CollectionOfFoo)e MVC è abbastanza intelligente da vedere che è una raccolta e renderizzare il singolo display per ogni elemento (al contrario di un parziale, che richiederebbe un esplicito per ciclo continuo).

Ho anche sentito che DisplayFor esegue il rendering di un modello di "sola lettura", ma non lo capisco: non posso lanciare un modulo lì?

Qualcuno può dirmi alcune altre ragioni? C'è un elenco / articolo da qualche parte che confronta i tre?


I concetti alla base dei modelli di editor e display sono chiaramente definiti nella documentazione di asp.net mvc 2. I modelli sono parziali che aderiscono a una convenzione specifica. Le situazioni che rendono i modelli migliori o peggiori dei vecchi parziali sono quasi strettamente dipendenti dal fatto che la convenzione valga la pena aderire o meno alla propria applicazione.
Nick Larsen,

Risposte:


301

EditorForvs DisplayForè semplice. La semantica dei metodi è generare viste di modifica / inserimento e visualizzazione / sola lettura (rispettivamente). Utilizzare DisplayForquando si visualizzano dati (ovvero quando si generano div e span che contengono i valori del modello). Utilizzare EditorForper modificare / inserire dati (ad es. Quando si generano tag di input all'interno di un modulo).

I metodi sopra indicati sono incentrati sul modello. Ciò significa che prenderanno in considerazione i metadati del modello (ad esempio è possibile annotare la classe del modello con [UIHintAttribute]o [DisplayAttribute]e ciò influenzerebbe il modello scelto per generare l'interfaccia utente per il modello. Di solito vengono anche utilizzati per i modelli di dati (ovvero modelli che rappresentare le righe in un database, ecc.)

D'altra parte Partialè incentrato sulla vista in quanto sei principalmente interessato a scegliere la vista parziale corretta. La vista non ha necessariamente bisogno di un modello per funzionare correttamente. Può avere solo un set comune di markup che viene riutilizzato in tutto il sito. Naturalmente, spesso si desidera influenzare il comportamento di questo parziale, nel qual caso è possibile passare a un modello di visualizzazione appropriato.

Non hai chiesto @Html.Actionquale merita anche una menzione qui. Potresti pensarlo come una versione più potente Partialin quanto esegue un'azione figlio del controller e quindi esegue il rendering di una vista (che di solito è una vista parziale). Ciò è importante perché l'azione figlio può eseguire una logica aziendale aggiuntiva che non appartiene a una vista parziale. Ad esempio, potrebbe rappresentare un componente del carrello. Il motivo per utilizzarlo è evitare di eseguire il lavoro relativo al carrello in tutti i controller dell'applicazione.

In definitiva la scelta dipende da cosa stai modellando nella tua applicazione. Ricorda anche che puoi mescolare e abbinare. Ad esempio, potresti avere una vista parziale che chiama l' EditorForhelper. Dipende davvero da cosa è l'applicazione e come fattorizzarla per incoraggiare il massimo riutilizzo del codice evitando la ripetizione.


4
È un'ottima risposta, esattamente quello che stavo cercando. In realtà, stavo puntando sul fatto che saresti venuto a rispondere a questa domanda. :) Grazie marcin.
RPM1984,

Come si usano le annotazioni per specificare un modello di visualizzazione e un modello di editor per una singola proprietà?
Stormwild

3
@stormwild usa la convenzione e dai un nome ai tuoi modelli in base al modello a cui si riferiscono (/Views/DisplayTemplates/MyModel.cshtml) o forzalo esplicitamente con l'annotazione UIHint.
Tom Wayson,

Qualche consiglio da scegliere per la creazione di una procedura guidata "registra utente" riutilizzabile? Voglio creare queste viste (e controller) in un assieme separato, se possibile. Ah, un modo per ridistribuire tra diversi team questi moduli / controller di mvc resuable. (abbiamo creato un unico modo per gestire l'utente / memorizzazione (servizi webapi) ... ma ogni team sta creando le proprie pagine mvc: <Grazie.
granadaCoder

Dove conservi quei modelli? Devo memorizzarli in Modelli condivisi / editor o è possibile memorizzarli direttamente nella cartella del controller corrente (quando ne ho bisogno solo lì)?
Santhos,

15

Certamente potrebbe personalizzare DisplayForper visualizzare una forma modificabile. Ma la convenzione è per DisplayForessere readonlyed EditorForessere per il montaggio. Attenersi alla convenzione farà in modo che qualunque cosa passi DisplayFor, farà lo stesso tipo di cose.


2
Non penso che ci sia davvero qualche domanda / dubbio su quando si dovrebbero usare i modelli di visualizzazione contro i modelli dell'editor. La vera domanda sembra essere quando dovresti usare i template contro i parziali. La tua risposta manca del tutto.
Joshua Hayes,

19
@Joshua - Penso che ci fosse qualche domanda a riguardo: "Ho anche sentito che DisplayFor esegue il rendering di un modello di" sola lettura ", ma non lo capisco - non posso lanciare un modulo lì?"
Robert Levy,

13

Giusto per dare valore al mio 2c, il nostro progetto sta usando una vista parziale con diverse schede jQuery e ciascuna scheda rende i suoi campi con una propria vista parziale. Questo ha funzionato bene fino a quando non abbiamo aggiunto una funzione in base alla quale alcune delle schede condividevano alcuni campi comuni. Il nostro primo approccio a questo è stato quello di creare un'altra vista parziale con questi campi comuni, ma questo è diventato molto goffo quando si utilizza EditorFor e DropDownListFor per eseguire il rendering dei campi e dei menu a discesa. Per rendere univoci gli ID e i nomi abbiamo dovuto rendere i campi con un prefisso in base alla vista parziale principale che lo stava eseguendo:

    <div id="div-@(idPrefix)2" class="toHide-@(idPrefix)" style="display:none">
    <fieldset>
        <label for="@(idPrefix).Frequency">Frequency<span style="color: #660000;"> *</span></label>

        <input name="@(idPrefix).Frequency"
               id="@(idPrefix)_Frequency"
               style="width: 50%;"
               type="text"
               value="@(defaultTimePoint.Frequency)"
               data-bind="value: viewState.@(viewStatePrefix).RecurringTimepoints.Frequency"
               data-val="true"
               data-val-required="The Frequency field is required."
               data-val-number="The field Frequency must be a number."
               data-val-range-min="1"
               data-val-range-max="24"
               data-val-range="The field Frequency must be between 1 and 24."
               data-val-ignore="true"/>

        @Html.ValidationMessage(idPrefix + ".Frequency")

        ... etc

    </fieldset>
</div>

Questo è diventato piuttosto brutto, quindi abbiamo deciso di utilizzare invece i modelli di editor, che hanno funzionato in modo molto più pulito. Abbiamo aggiunto un nuovo modello di visualizzazione con i campi comuni, aggiunto un modello di editor corrispondente e reso i campi utilizzando il modello di editor da diverse viste principali. Il modello dell'editor esegue il rendering corretto di ID e nomi.

Quindi in breve, un motivo convincente per noi di usare i modelli dell'editor era la necessità di rendere alcuni campi comuni in più schede. Le viste parziali non sono progettate per questo, ma i modelli dell'editor gestiscono perfettamente lo scenario.


1
Ho avuto un problema simile usando le schede e ho finito con BeginCollectionItem di Steve Sanderson che genera l'id di controllo unico per te: blog.stevensanderson.com/2010/01/28/…
Wilky

1

Utilizzare l' _partialapproccio vista se:

  1. Visualizza la logica centrica
  2. Cosa mantenere tutti _partialgli HTML correlati alla vista solo in questa vista. Nel metodo modello, dovrai mantenere un po 'di HTML fuori dalla vista modello come "Intestazione principale o qualsiasi bordo / impostazioni esterno.
  3. Vuoi rendere parziale la vista con la logica (dal controller) usando URL.Action("action","controller").

Motivi per utilizzare il modello:

  1. Vuoi rimuovere ForEach(Iterator). Il modello è abbastanza buono per identificare il modello come tipo di elenco. Lo farà automaticamente.
  2. Model Centric Logic. Se si trovano più viste nella stessa schermata per la cartella Modello, il rendering dipenderà dal Modello passato.

1

Un'altra differenza che non è stata menzionata finora è che una vista parziale non aggiunge prefissi di modello mentre un modello fa Ecco il problema

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.