ASP.NET MVC 3 - Teilweise vs Anzeigevorlage vs Editorvorlage

303

Der Titel sollte also für sich selbst sprechen.

Um wiederverwendbare Komponenten in ASP.NET MVC zu erstellen, haben wir drei Optionen (möglicherweise andere, die ich nicht erwähnt habe):

Teilansicht:

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

Benutzerdefinierte Editor-Vorlage:

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

Benutzerdefinierte Anzeigevorlage:

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

In Bezug auf die tatsächliche Ansicht / HTML sind alle drei Implementierungen identisch:

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

Meine Frage ist also: Wann / wie entscheiden Sie, welche der drei Sie verwenden möchten?

Was ich wirklich suche, ist eine Liste von Fragen, die Sie sich stellen müssen, bevor Sie eine erstellen, anhand derer anhand der Antworten entschieden werden kann, welche Vorlage verwendet werden soll.

Hier sind die 2 Dinge, die ich mit EditorFor / DisplayFor besser gefunden habe:

  1. Sie berücksichtigen Modellhierarchien beim Rendern von HTML-Helfern (z. B. wenn Sie ein "Bar" -Objekt in Ihrem "Foo" -Modell haben, werden die HTML-Elemente für "Bar" mit "Foo.Bar.ElementName" gerendert, während ein Teil " Elementname ").

  2. Robuster, z. B. wenn Sie List<T>etwas in Ihrem ViewModel haben, das Sie verwenden könnten @Html.DisplayFor(model => model.CollectionOfFoo), und MVC ist intelligent genug, um zu sehen, dass es sich um eine Sammlung handelt, und die einzelne Anzeige für jedes Element zu rendern (im Gegensatz zu einem Teil, für das ein explizites Element erforderlich wäre Schleife).

Ich habe auch gehört, dass DisplayFor eine "schreibgeschützte" Vorlage rendert, aber ich verstehe das nicht - könnte ich dort kein Formular werfen?

Kann mir jemand andere Gründe nennen? Gibt es irgendwo eine Liste / einen Artikel, in dem die drei verglichen werden?

RPM1984
quelle
Die Konzepte hinter Editor- und Anzeigevorlagen sind in der Dokumentation zu asp.net mvc 2 klar definiert. Vorlagen sind Teilvorlagen, die einer bestimmten Konvention entsprechen. Die Situationen, in denen Vorlagen besser oder schlechter als alte Teilvorlagen sind, hängen fast ausschließlich davon ab, ob die Konvention in Ihrer Anwendung eingehalten werden sollte oder nicht.
Nick Larsen

Antworten:

301

EditorForvs DisplayForist einfach. Die Semantik der Methoden besteht darin, Ansichten zum Bearbeiten / Einfügen bzw. Anzeigen / Nur Lesen zu generieren. Wird DisplayForbeim Anzeigen von Daten verwendet (dh wenn Sie Divs und Spans generieren, die die Modellwerte enthalten). Verwendung EditorForbeim Bearbeiten / Einfügen von Daten (dh beim Generieren von Eingabe-Tags in einem Formular).

Die oben genannten Methoden sind modellzentriert. Dies bedeutet, dass sie die Modellmetadaten berücksichtigen (zum Beispiel könnten Sie Ihre Modellklasse mit [UIHintAttribute]oder kommentieren [DisplayAttribute]und dies würde beeinflussen, welche Vorlage ausgewählt wird, um die Benutzeroberfläche für das Modell zu generieren. Sie werden normalerweise auch für Datenmodelle verwendet (dh Modelle, die Zeilen in einer Datenbank darstellen usw.)

Auf der anderen Seite Partialist die Ansicht insofern zentriert, als Sie sich hauptsächlich mit der Auswahl der richtigen Teilansicht befassen. Die Ansicht benötigt nicht unbedingt ein Modell, um korrekt zu funktionieren. Es kann nur einen gemeinsamen Satz von Markups geben, die auf der gesamten Site wiederverwendet werden. Natürlich möchten Sie häufig das Verhalten dieses Teils beeinflussen. In diesem Fall möchten Sie möglicherweise ein geeignetes Ansichtsmodell übergeben.

Sie haben nicht gefragt, @Html.Actionwas auch hier eine Erwähnung verdient. Sie können sich das als eine leistungsstärkere Version Partialvorstellen, indem es eine untergeordnete Controller-Aktion ausführt und dann eine Ansicht rendert (die normalerweise eine Teilansicht ist). Dies ist wichtig, da die untergeordnete Aktion zusätzliche Geschäftslogik ausführen kann, die nicht zu einer Teilansicht gehört. Zum Beispiel könnte es eine Warenkorbkomponente darstellen. Der Grund für die Verwendung besteht darin, zu vermeiden, dass die Warenkorbarbeiten in jedem Controller in Ihrer Anwendung ausgeführt werden.

Letztendlich hängt die Wahl davon ab, was Sie in Ihrer Anwendung modellieren. Denken Sie auch daran, dass Sie mischen und anpassen können. Beispielsweise könnten Sie eine Teilansicht haben, die den EditorForHelfer aufruft . Es hängt wirklich davon ab, was Ihre Anwendung ist und wie Sie sie berücksichtigen, um eine maximale Wiederverwendung von Code zu fördern und Wiederholungen zu vermeiden.

Marcind
quelle
4
Das ist eine großartige Antwort, genau das, wonach ich gesucht habe. In Wirklichkeit habe ich mich darauf verlassen, dass Sie kommen und darauf antworten würden. :) Danke marcin.
RPM1984
Wie verwenden Sie Anmerkungen, um eine Anzeigevorlage und eine Editorvorlage für eine einzelne Eigenschaft anzugeben?
Stormwild
3
@stormwild verwendet entweder die Konvention und benennt Ihre Vorlagen nach dem Modell, auf das sie sich beziehen (/Views/DisplayTemplates/MyModel.cshtml), oder erzwingt sie explizit mit der UIHint-Annotation.
Tom Wayson
Irgendwelche Ratschläge, die Sie zum Erstellen eines wiederverwendbaren Assistenten zum Registrieren von Benutzern auswählen sollten? Ich möchte diese Ansichten (und Controller) nach Möglichkeit in einer separaten Assembly erstellen. Aka, eine Möglichkeit, diese wiederverwendbaren MVC-Formulare / Controller auf mehrere Teams zu verteilen. (Wir haben eine einzige Möglichkeit für den Umgang mit Benutzern / Speichern (Webapi-Dienste) geschaffen ... aber jedes Team erstellt seine eigenen MVC-Seiten: <Danke.
GranadaCoder
Wo speichern Sie diese Vorlagen? Muss ich sie in Shared / EditorTemplates speichern oder ist es möglich, sie direkt im aktuellen Controller-Ordner zu speichern (wenn ich sie nur dort benötige)?
Santhos
15

Sie sicherlich könnte anpassen DisplayForeine editierbare Form angezeigt werden soll . Aber die Konvention ist für DisplayFordas Sein readonlyund EditorForfür das Bearbeiten. Wenn Sie sich an die Konvention halten, wird sichergestellt, dass unabhängig davon, worauf Sie sich einlassen DisplayFor, dasselbe getan wird.

Robert Levy
quelle
2
Ich glaube nicht, dass es wirklich Fragen / Zweifel gibt, wann man Anzeigevorlagen gegen Editorvorlagen verwenden sollte. Die eigentliche Frage scheint zu sein, wann Sie Vorlagen oder Teilvorlagen verwenden sollten. Ihre Antwort verfehlt dies völlig.
Joshua Hayes
19
@Joshua - Ich denke, es gab einige Fragen dazu: "Ich habe auch gehört, dass DisplayFor eine" schreibgeschützte "Vorlage rendert, aber ich verstehe das nicht - konnte ich dort kein Formular werfen?"
Robert Levy
13

Um meinen Wert für 2c zu bestimmen, verwendet unser Projekt eine Teilansicht mit mehreren jQuery-Registerkarten, und jede Registerkarte rendert ihre Felder mit einer eigenen Teilansicht. Dies funktionierte einwandfrei, bis wir eine Funktion hinzugefügt haben, mit der einige der Registerkarten einige gemeinsame Felder gemeinsam nutzen. Unser erster Ansatz bestand darin, eine weitere Teilansicht mit diesen allgemeinen Feldern zu erstellen. Dies wurde jedoch sehr umständlich, wenn EditorFor und DropDownListFor zum Rendern von Feldern und Dropdowns verwendet wurden. Um die IDs und Namen eindeutig zu machen, mussten wir die Felder mit einem Präfix rendern, abhängig von der übergeordneten Teilansicht, in der sie gerendert wurden:

    <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>

Das wurde ziemlich hässlich, also entschieden wir uns stattdessen für Editor-Vorlagen, was viel sauberer funktionierte. Wir haben ein neues Ansichtsmodell mit den allgemeinen Feldern hinzugefügt, eine passende Editorvorlage hinzugefügt und die Felder mithilfe der Editorvorlage aus verschiedenen übergeordneten Ansichten gerendert. Die Editor-Vorlage rendert die IDs und Namen korrekt.

Kurz gesagt, ein überzeugender Grund für die Verwendung von Editor-Vorlagen war die Notwendigkeit, einige gemeinsame Felder in mehreren Registerkarten zu rendern. Teilansichten sind nicht dafür ausgelegt, aber Editor-Vorlagen behandeln das Szenario perfekt.

Ciaran Bruen
quelle
1
Ich hatte ein ähnliches Problem mit Tabs und habe schließlich Steve Sandersons BeginCollectionItem verwendet, das die eindeutigen Steuerelement- IDs
Wilky
1

Verwenden Sie den _partialAnsichtsansatz, wenn:

  1. Zentrische Logik anzeigen
  2. Was alles zu behalten _partial ansichtsbezogene HTML nur in dieser Ansicht . Bei der Vorlagenmethode müssen Sie HTML-Code außerhalb der Vorlagenansicht beibehalten, z. B. "Hauptkopfzeile oder äußere Rahmen / Einstellungen".
  3. Möchten Sie eine Teilansicht mit Logik (vom Controller) mit rendern URL.Action("action","controller").

Gründe für die Verwendung der Vorlage:

  1. Möchten Sie entfernen ForEach(Iterator) . Die Vorlage ist gut genug, um das Modell als Listentyp zu identifizieren. Es wird es automatisch tun.
  2. Modellzentrische Logik. Wenn mehrere Ansichten in derselben Anzeige für den Vorlagenordner gefunden werden, hängt das Rendern vom übergebenen Modell ab.
Jitendra Joshi
quelle
1

Ein weiterer Unterschied, der bisher nicht erwähnt wurde, besteht darin, dass in einer Teilansicht keine Modellpräfixe hinzugefügt werden, während dies in einer Vorlage der Fall ist. Hier ist das Problem

erhan355
quelle