ASP.NET MVC 3 - Частичный или шаблон отображения и шаблон редактора

303

Таким образом, название должно говорить само за себя.

Для создания повторно используемых компонентов в ASP.NET MVC у нас есть 3 варианта (могут быть и другие, о которых я не упомянул):

Частичный вид:

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

Пользовательский шаблон редактора:

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

Пользовательский шаблон отображения:

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

С точки зрения фактического View / HTML все три реализации идентичны:

@model WebApplications.Models.FooObject

<!-- Bunch of HTML -->

Итак, мой вопрос - когда / как вы решаете, какой из трех использовать?

Что я действительно ищу, так это список вопросов, которые нужно задать себе перед тем, как создавать, ответы на которые можно использовать, чтобы решить, какой шаблон использовать.

Вот две вещи, которые я нашел лучше с EditorFor / DisplayFor:

  1. Они уважают иерархии моделей при рендеринге помощников HTML (например, если у вас есть объект "Bar" в вашей модели "Foo", элементы HTML для "Bar" будут отображаться с "Foo.Bar.ElementName", тогда как частичное будет иметь " ElementName ").

  2. Более надежный, например, если у вас есть List<T>что-то в вашей ViewModel, вы можете использовать его @Html.DisplayFor(model => model.CollectionOfFoo), и MVC достаточно умен, чтобы видеть его как коллекцию и отображать одно отображение для каждого элемента (в отличие от Partial, для которого требуется явное петля).

Я также слышал, что DisplayFor отображает шаблон «только для чтения», но я не понимаю этого - разве я не могу добавить туда форму?

Может кто-нибудь сказать мне другие причины? Есть ли где-нибудь список / статья, сравнивающая три?

RPM1984
источник
Концепции, лежащие в основе редактора и шаблонов отображения, четко определены в документации для asp.net mvc 2. Шаблоны - это частичные элементы, соответствующие определенному соглашению. Ситуации, которые делают шаблоны лучше или хуже старых партиалов, почти строго зависят от того, стоит ли соглашение в вашем приложении.
Ник Ларсен

Ответы:

301

EditorForпротив DisplayForпросто. Семантика методов состоит в том, чтобы генерировать представления редактирования / вставки и отображения / только для чтения (соответственно). Используется DisplayForпри отображении данных (т. Е. При создании элементов div и span, которые содержат значения модели). Используется EditorForпри редактировании / вставке данных (т. Е. При создании входных тегов внутри формы).

Вышеуказанные методы ориентированы на модель. Это означает, что они будут учитывать метаданные модели (например, вы можете аннотировать класс вашей модели с помощью [UIHintAttribute]или, [DisplayAttribute]и это будет влиять на то, какой шаблон будет выбран для создания пользовательского интерфейса для модели. Они также обычно используются для моделей данных (то есть моделей, которые представлять строки в базе данных и т. д.)

С другой стороны, Partialон ориентирован на просмотр, так как вас больше всего интересует выбор правильного частичного вида. Представлению не обязательно нужна модель для правильного функционирования. У него может быть общий набор разметки, который повторно используется по всему сайту. Конечно, часто вы хотите повлиять на поведение этой части, и в этом случае вы можете захотеть передать соответствующую модель представления.

Вы не спрашивали о том, @Html.Actionчто также заслуживает упоминания здесь. Вы можете думать о нем как о более мощной версии, Partialзаключающейся в том, что он выполняет дочернее действие контроллера и затем отображает представление (которое обычно является частичным представлением). Это важно, потому что дочернее действие может выполнять дополнительную бизнес-логику, которая не принадлежит частичному представлению. Например, он может представлять компонент корзины покупок. Причиной его использования является недопущение выполнения работ, связанных с корзиной покупок, в каждом контроллере вашего приложения.

В конечном итоге выбор зависит от того, что именно вы моделируете в своем приложении. Также помните, что вы можете смешивать и сочетать. Например, у вас может быть частичное представление, которое вызывает EditorForпомощника. Это действительно зависит от того, что представляет собой ваше приложение и как его учитывать, чтобы стимулировать максимальное повторное использование кода, избегая при этом повторения.

marcind
источник
4
Это отличный ответ, именно то, что я искал. На самом деле я рассчитывал на то, что ты придешь и ответишь на это. :) Спасибо, Марцин.
RPM1984
Как вы используете аннотации, чтобы указать шаблон отображения и шаблон редактора для одного свойства?
stormwild
3
@stormwild либо используйте соглашение и назовите ваши шаблоны в соответствии с моделью, к которой они относятся (/Views/DisplayTemplates/MyModel.cshtml), либо явным образом принудительно используйте их с аннотацией UIHint.
Том Уэйсон
Какой совет вы бы выбрали для создания многоразового мастера регистрации пользователей? Я хочу создать эти представления (и контроллеры) в отдельной сборке, если это возможно. Ака, способ перераспределить между несколькими командами эти пригодные для повторения формы / контроллеры mvc. (мы создали единый способ обработки пользователя / хранения (сервисы webapi) ... но каждая команда создает свои собственные страницы mvc: <Спасибо.
granadaCoder,
Где вы храните эти шаблоны? Нужно ли хранить их в Shared / EditorTemplates или можно хранить их непосредственно в текущей папке контроллера (когда они нужны мне только там)?
Сантос
15

Вы, конечно, можете настроить DisplayForотображение редактируемой формы. Но соглашение предназначено для того, DisplayForчтобы быть readonlyи EditorForбыть для редактирования. Соблюдение соглашения гарантирует, что независимо от того, во что вы переходите DisplayFor, оно будет делать то же самое.

Роберт Леви
источник
2
Я не думаю, что на самом деле есть какие-либо вопросы / сомнения относительно того, когда следует использовать шаблоны отображения вместо шаблонов редактора. Похоже, реальный вопрос заключается в том, когда следует использовать шаблоны против частичных. Ваш ответ полностью пропускает это.
Джошуа Хейс
19
@ Джошуа - я думаю, что был какой-то вопрос к этому: «Я также слышал, что DisplayFor отображает шаблон« только для чтения », но я не понимаю этого - разве я не могу добавить туда форму?»
Роберт Леви
13

Просто для того, чтобы оценить мой уровень 2c, наш проект использует частичное представление с несколькими вкладками jQuery, и каждая вкладка отображает свои поля со своим частичным представлением. Это работало нормально, пока мы не добавили функцию, благодаря которой некоторые вкладки имели общие поля. Наш первый подход к этому состоял в создании другого частичного представления с этими общими полями, но это стало очень неуклюжим при использовании EditorFor и DropDownListFor для визуализации полей и выпадающих списков. Чтобы получить уникальные идентификаторы и имена, мы должны были отобразить поля с префиксом в зависимости от родительского частичного представления, которое его отображало:

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

Это стало довольно уродливо, поэтому мы решили использовать вместо этого шаблоны редактора, которые работали намного чище. Мы добавили новую модель представления с общими полями, добавили соответствующий шаблон редактора и визуализировали поля с использованием шаблона редактора из разных родительских представлений. Шаблон редактора правильно отображает идентификаторы и имена.

Короче говоря, убедительной причиной использования шаблонов редактора была необходимость отображать некоторые общие поля на нескольких вкладках. Частичные представления не предназначены для этого, но шаблоны редактора отлично справляются со сценарием.

Кьяран Бруен
источник
1
У меня была похожая проблема с использованием вкладок, и в итоге я использовал BeginCollectionItem Стива Сандерсона, который генерирует для вас уникальный идентификатор элемента
Wilky
1

Используйте _partialподход просмотра, если:

  1. Посмотреть Centric Logic
  2. Что сохранить все _partialпредставления, связанные HTML только в этом представлении. В методе шаблона вам нужно будет оставить некоторый HTML вне представления шаблона, например «Главный заголовок» или любую внешнюю границу / настройки.
  3. Хотите визуализировать частичное представление с помощью логики (из контроллера) URL.Action("action","controller").

Причины использовать шаблон:

  1. Хочу удалить ForEach(Iterator). Шаблон достаточно хорош, чтобы идентифицировать модель как тип списка. Это будет сделано автоматически.
  2. Модельно-ориентированная логика. Если в одной папке display для шаблона находятся несколько видов, рендеринг будет зависеть от пройденной модели.
Джитендра Джоши
источник
1

Еще одно различие, которое не было упомянуто до сих пор является то , что PartialView не добавляет модели префиксов в то время как шаблон делает здесь является вопрос

erhan355
источник