ASP.NET MVC 3 – modelo vs modelo de exibição vs editor parcial

Então, o título deve falar por si.

Para criar componentes reutilizáveis ​​no ASP.NET MVC, temos 3 opções (outras que não mencionei):

Vista Parcial:

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

Modelo de editor personalizado:

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

Modelo de exibição personalizada:

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

Em termos do View / HTML real, todas as três implementações são idênticas:

 @model WebApplications.Models.FooObject  

Então, minha pergunta é – quando / como você decide qual dos três usar?

O que eu realmente procuro é uma lista de perguntas a serem feitas antes de criar uma, para a qual as respostas podem ser usadas para decidir qual modelo usar.

Aqui estão as duas coisas que eu encontrei melhor com EditorFor / DisplayFor:

  1. Eles respeitam hierarquias de modelo ao renderizar ajudantes HTML (por exemplo, se você tiver um object “Bar” em seu modelo “Foo”, os elementos HTML para “Bar” serão renderizados com “Foo.Bar.ElementName”, enquanto um parcial terá ” ElementName “).

  2. Mais robusto, por exemplo, se você tivesse uma List de algo em seu ViewModel, você poderia usar @Html.DisplayFor(model => model.CollectionOfFoo) , e o MVC é inteligente o suficiente para ver que é uma coleção e renderizar a exibição única para cada item (em oposição a um Partial, o que exigiria um loop for explícito).

Eu também ouvi DisplayFor processa um modelo “somente leitura”, mas eu não entendo isso – eu não poderia jogar um formulário lá?

Alguém pode me dizer algumas outras razões? Existe uma lista / artigo em algum lugar comparando os três?

EditorFor vs EditorFor é simples. A semântica dos methods é gerar visualizações editar / inserir e exibir / somente leitura (respectivamente). Use DisplayFor ao exibir dados (ou seja, quando você gera divs e spans que contêm os valores do modelo). Use EditorFor ao editar / inserir dados (ou seja, quando você gerar tags de input dentro de um formulário).

Os methods acima são centrados no modelo. Isso significa que eles levarão em consideração os metadados do modelo (por exemplo, você poderia anotar sua class de modelo com [UIHintAttribute] ou [DisplayAttribute] e isso influenciaria qual modelo é escolhido para gerar a UI para o modelo. Eles também são geralmente usados ​​para modelos de dados (ou seja, modelos que representam linhas em um database, etc)

Por outro lado, o Partial é centrado na visão, na medida em que você está mais preocupado em escolher a visão parcial correta. A visão não precisa necessariamente de um modelo para funcionar corretamente. Ele pode ter apenas um conjunto comum de marcação que é reutilizado em todo o site. É claro que muitas vezes você deseja afetar o comportamento dessa parcial, caso em que você pode querer passar um modelo de exibição apropriado.

Você não perguntou sobre o @Html.Action que também merece uma menção aqui. Você poderia pensar nisso como uma versão mais poderosa do Partial na medida em que executa uma ação filho do controlador e, em seguida, renderiza uma visão (que geralmente é uma visão parcial). Isso é importante porque a ação filho pode executar uma lógica de negócios adicional que não pertence a uma visão parcial. Por exemplo, poderia representar um componente de carrinho de compras. O motivo para usá-lo é evitar a execução do trabalho relacionado ao carrinho de compras em todos os controladores em seu aplicativo.

Em última análise, a escolha depende do que você está modelando em seu aplicativo. Lembre-se também que você pode misturar e combinar. Por exemplo, você poderia ter uma visão parcial que chama o assistente EditorFor . Isso realmente depende do seu aplicativo e de como fatorá-lo para incentivar a reutilização máxima do código, evitando a repetição.

Você certamente poderia personalizar o DisplayFor para exibir um formulário editável. Mas a convenção é que o DisplayFor seja readonly para readonly e que o EditorFor seja para edição. Manter a convenção irá garantir que, não importa o que você passe para o DisplayFor , ele fará o mesmo tipo de coisa.

Apenas para dar meu 2c valor, nosso projeto está usando uma visão parcial com várias abas jQuery, e cada aba renderizando seus campos com sua própria visão parcial. Isso funcionou bem até que adicionamos um recurso pelo qual algumas das guias compartilhavam alguns campos comuns. Nossa primeira abordagem para isso foi criar outra visão parcial com esses campos comuns, mas isso ficou muito desajeitado ao usar EditorFor e DropDownListFor para renderizar campos e menus suspensos. A fim de obter os ids e nomes exclusivos, tivemos que renderizar os campos com um prefixo, dependendo da visualização parcial principal que estava renderizando:

   

Isso ficou muito feio, então decidimos usar o Editor Templates, que funcionou muito mais limpo. Adicionamos um novo modelo de vista com os campos comuns, adicionamos um modelo de editor correspondente e renderizamos os campos usando o modelo de editor de diferentes exibições pai. O modelo de editor processa corretamente os ids e nomes.

Então, em suma, uma razão convincente para usarmos o Editor Templates foi a necessidade de renderizar alguns campos comuns em várias guias. As visualizações parciais não são projetadas para isso, mas os Modelos do Editor lidam perfeitamente com o cenário.

Use a abordagem de visão _partial se:

  1. Ver Lógica Centralizada
  2. O que manter todo o HTML relacionado à visualização parcial somente nesta exibição. No método de modelo, você terá que manter algum HTML fora da Exibição de modelo, como “Cabeçalho principal ou qualquer borda externa / configurações”.
  3. Deseja renderizar a visualização parcial com lógica (do controlador) usando URL.Action("action","controller") .

Razões para usar o modelo:

  1. Deseja remover ForEach(Iterator) . O modelo é bom o suficiente para identificar o Modelo como um tipo de lista. Ele fará isso automaticamente.
  2. Lógica Centric Modelo. Se várias exibições forem encontradas na mesma exibição da pasta Modelo, a renderização dependerá do Modelo Aprovado.

Outra diferença que não foi mencionada até agora é que um partialview não adiciona prefixos de modelo enquanto um template faz. Aqui está o problema