ASP.NET MVC 3 - Szablon częściowy vs. szablon wyświetlania a szablon edytora

303

Tak więc tytuł powinien mówić sam za siebie.

Aby utworzyć komponenty wielokrotnego użytku w ASP.NET MVC, mamy 3 opcje (mogą to być inne, o których nie wspomniałem):

Częściowy widok:

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

Szablon edytora niestandardowego:

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

Niestandardowy szablon wyświetlania:

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

Pod względem faktycznego widoku / HTML wszystkie trzy implementacje są identyczne:

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

Więc moje pytanie brzmi - kiedy / jak decydujesz, którego z trzech użyć?

To, czego naprawdę szukam, to lista pytań, które należy sobie zadać przed utworzeniem jednego, na które odpowiedzi można użyć, aby zdecydować, który szablon użyć.

Oto 2 rzeczy, które znalazłem lepiej dzięki EditorFor / DisplayFor:

  1. Przestrzegają hierarchii modeli podczas renderowania pomocników HTML (np. Jeśli masz model „Bar” w modelu „Foo”, elementy HTML dla „Bar” będą renderowane z „Foo.Bar.ElementName”, podczas gdy część będzie miała „ ElementName ”).

  2. Bardziej solidny, np. Jeśli masz List<T>coś w ViewModel, możesz użyć @Html.DisplayFor(model => model.CollectionOfFoo), a MVC jest wystarczająco inteligentny, aby zobaczyć, że jest to kolekcja i renderować pojedynczy wyświetlacz dla każdego elementu (w przeciwieństwie do częściowego, który wymagałby jawnego wyrażenia dla pętla).

Słyszałem również, że DisplayFor renderuje szablon „tylko do odczytu”, ale nie rozumiem tego - czy nie mogę tam wrzucić formularza?

Czy ktoś może mi powiedzieć inne powody? Czy jest gdzieś lista / artykuł porównujący te trzy?

RPM1984
źródło
Pojęcia dotyczące edytora i szablonów wyświetlania są jasno zdefiniowane w dokumentacji asp.net mvc 2. Szablony są częściami zgodnymi z określoną konwencją. Sytuacje, w których szablony są lepsze lub gorsze niż stare częściowe, są prawie ściśle zależne od tego, czy konwencja jest warta zastosowania w aplikacji.
Nick Larsen

Odpowiedzi:

301

EditorForvs DisplayForjest proste. Semantyka metod polega na generowaniu (odpowiednio) widoków edycji / wstawiania i wyświetlania / tylko do odczytu. Służy do DisplayForwyświetlania danych (tj. Do generowania div i rozpiętości zawierających wartości modelu). Służy do EditorForedytowania / wstawiania danych (tj. Do generowania znaczników wejściowych w formularzu).

Powyższe metody są ukierunkowane na model. Oznacza to, że wezmą pod uwagę metadane modelu (na przykład możesz dodać adnotację do swojej klasy modelu [UIHintAttribute]lub, [DisplayAttribute]co wpłynie na to, który szablon zostanie wybrany do wygenerowania interfejsu użytkownika dla modelu. Są one również zwykle używane w modelach danych (tj. Modelach, które reprezentują wiersze w bazie danych itp.)

Z drugiej strony Partialkoncentruje się na widoku, ponieważ w większości zajmujesz się wyborem prawidłowego widoku częściowego. Widok niekoniecznie potrzebuje modelu do poprawnego działania. Może mieć po prostu wspólny zestaw znaczników, który jest ponownie wykorzystywany w całej witrynie. Oczywiście często chcesz wpłynąć na zachowanie tego częściowego, w którym to przypadku możesz chcieć przekazać odpowiedni model widoku.

Nie zapytałeś o to, @Html.Actionco również zasługuje na wzmiankę tutaj. Możesz myśleć o tym jako o bardziej wydajnej wersji Partial, ponieważ wykonuje ona działanie potomne kontrolera, a następnie renderuje widok (który jest zwykle widokiem częściowym). Jest to ważne, ponieważ akcja potomna może wykonać dodatkową logikę biznesową, która nie należy do częściowego widoku. Na przykład może reprezentować element koszyka. Powodem korzystania z niego jest unikanie wykonywania zadań związanych z koszykiem na każdym kontrolerze w aplikacji.

Ostatecznie wybór zależy od tego, co modelujesz w swojej aplikacji. Pamiętaj też, że możesz miksować i dopasowywać. Na przykład możesz mieć częściowy widok, który wywołuje EditorForpomocnika. To naprawdę zależy od tego, jaka jest twoja aplikacja i jak ją uwzględnić, aby zachęcić do maksymalnego ponownego użycia kodu, unikając powtórzeń.

marcind
źródło
4
To świetna odpowiedź, dokładnie tego szukałem. W rzeczywistości polegałem na tym, że przyszedłeś i odpowiedziałeś na to. :) Dzięki marcin.
RPM1984
Jak używasz adnotacji, aby określić szablon wyświetlania i szablon edytora dla pojedynczej właściwości?
stormwild
3
@stormwild albo stosuje konwencję i nazywa szablony według modelu, do którego się odnoszą (/Views/DisplayTemplates/MyModel.cshtml), lub jawnie wymusza to z adnotacją UIHint.
Tom Wayson
Czy masz jakieś porady dotyczące tworzenia kreatora „zarejestruj użytkownika” wielokrotnego użytku? Chcę utworzyć te widoki (i kontrolery) w oddzielnym zestawie, jeśli to możliwe. Aka, sposób na redystrybucję wśród kilku zespołów tych nadających się do ponownego użytku formularzy / kontrolerów mvc. (stworzyliśmy jeden sposób obsługi użytkowników / przechowywania (usługi webapi) ... ale każdy zespół tworzy własne strony mvc: <Dzięki.
granadaCoder
Gdzie przechowujesz te szablony? Czy muszę je przechowywać w folderze Shared / EditorTemplates, czy też można je przechowywać bezpośrednio w bieżącym folderze kontrolera (kiedy potrzebuję ich tylko tam)?
Santhos
15

Z pewnością można dostosować, DisplayForaby wyświetlać formularz do edycji. Ale konwencja ma DisplayForbyć readonlyi EditorForbyć do edycji. Trzymanie się konwencji zapewni, że bez względu na to, na co wpadniesz DisplayFor, zrobi to samo.

Robert Levy
źródło
2
Nie sądzę, aby naprawdę istniało pytanie / wątpliwości, kiedy należy używać szablonów wyświetlania zamiast szablonów edytora. Wydaje się, że prawdziwe pytanie brzmi, kiedy należy używać szablonów w porównaniu z częściami. Twoja odpowiedź całkowicie tego brakuje.
Joshua Hayes
19
@Joshua - myślę, że było na to pytanie: „Słyszałem również, że DisplayFor renderuje szablon„ tylko do odczytu ”, ale nie rozumiem tego - czy nie mogę tam wrzucić formularza?”
Robert Levy
13

Aby dać moją wartość 2c, nasz projekt używa widoku częściowego z kilkoma zakładkami jQuery, a każda karta renderuje swoje pola z własnym widokiem częściowym. Działało to dobrze, dopóki nie dodaliśmy funkcji, dzięki której niektóre karty udostępniały niektóre typowe pola. Naszym pierwszym podejściem do tego było utworzenie kolejnego widoku częściowego z tymi wspólnymi polami, ale stało się to bardzo niewygodne przy użyciu EditorFor i DropDownListFor do renderowania pól i list rozwijanych. Aby uzyskać unikalne identyfikatory i nazwy, musieliśmy renderować pola z prefiksem w zależności od nadrzędnego widoku częściowego, który je renderował:

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

Stało się to dość brzydkie, dlatego zdecydowaliśmy się na użycie szablonów edytora, które działały znacznie lepiej. Dodaliśmy nowy model widoku ze wspólnymi polami, dodaliśmy pasujący szablon edytora i wyrenderowaliśmy pola przy użyciu szablonu edytora z różnych widoków nadrzędnych. Szablon edytora poprawnie renderuje identyfikatory i nazwy.

Krótko mówiąc, ważnym powodem, dla którego używamy szablonów edytora, była konieczność renderowania niektórych wspólnych pól na wielu kartach. Widoki częściowe nie są do tego przeznaczone, ale szablony edytora doskonale obsługują scenariusz.

Ciaran Bruen
źródło
1
Miałem podobny problem z kartami i skończyłem na BeginCollectionItem Steve'a Sandersona, który generuje dla ciebie unikalny identyfikator kontrolny: blog.stevensanderson.com/2010/01/28/…
Wilky
1

Zastosuj _partialpodejście widoku, jeśli:

  1. Zobacz Centric Logic
  2. Co zachować cały _partialHTML związany z widokiem tylko w tym widoku. W metodzie szablonu będziesz musiał trzymać trochę HTML poza widokiem szablonu, np. „Główny nagłówek lub dowolne zewnętrzne obramowanie / ustawienia.
  3. Chcesz renderować widok częściowy za pomocą logiki (z kontrolera) przy użyciu URL.Action("action","controller").

Powody korzystania z szablonu:

  1. Chcesz usunąć ForEach(Iterator). Szablon wystarcza do zidentyfikowania modelu jako typu listy. Zrobi to automatycznie.
  2. Model Centric Logic. Jeśli w tym samym wyświetlaczu dla folderu szablonów znaleziono wiele widoków, renderowanie będzie zależeć od modelu przekazywanego.
jitendra joshi
źródło
1

Inną różnicą, o której nie wspomniano do tej pory, jest to, że widok częściowy nie dodaje prefiksów modelu, a robi to szablon Oto problem

erhan355
źródło