Como lidar com visualizações complexas (consistindo de várias partes) no aplicativo da Web MVC

7

Digamos que estou escrevendo um aplicativo da web de blog usando o padrão MVC. O layout típico da página principal do aplicativo de blog é - algum tipo de índice de postagem na parte principal e, além disso, existem algumas partes adicionais, como linha do tempo, painel de navegação de tags, painel de inscrição etc. Esses controles também aparecem em um único pós-visualização e pode aparecer em outras visualizações que possuo.

Minha pergunta é - como devo lidar com esses painéis de lado nas minhas visualizações e controladores. Eu vejo três abordagens aqui:

  1. Crie uma grande classe de modelo de exibição que contenha todas as informações necessárias para renderizar as exibições (índice ou postagem única). Nesse caso, eu poderia transformar esses painéis de lado em visualizações parciais e chamá-los da visualização sendo renderizados como parte desse grande modelo de visualização. A desvantagem é - terei o viewmodel de preenchimento de código espalhado entre vários métodos de controlador, o que significa que o código é duplicado. O que é muito ruim.

  2. Crie outra camada de exibição de renderização. Digamos, a camada superior de renderização recebe uma parte já renderizada de html, ou funções que, quando chamadas, produzem um html. A camada abaixo desta "combinação de camadas parciais" daria apenas visualizações parciais para cada painel que eu desejar, incluindo o conteúdo principal. A desvantagem aqui - uso de memória. A maioria das estruturas modernas processa htmls diretamente no fluxo de saída, mas nessa abordagem as visualizações parciais seriam renderizadas primeiro em objetos de string - o que leva à sobrecarga da memória.

  3. Use algo como "RenderAction" do asp.net mvc, que chama um método de controlador de uma exibição. Eu acho que esta é a pior solução de 3 dada, porque deixa cair uma abordagem MVC.

A questão não está vinculada a nenhuma estrutura específica, quero entender a maneira geral de fazer coisas assim.

ATUALIZAR

Depois de uma resposta dada, descobri que o post não está claro. Atualização tão razoável aqui:

No termo viewmodel, eu entendo um objeto que contém todos os dados necessários para renderizar uma exibição específica.

Todas as três abordagens envolvem a construção de vistas parciais com seu próprio modelo de vista. Por exemplo (usando a sintaxe C #):

class SinglePostViewModel {
  string Text {get;set;}
  string Title {get;set;}
  string Slug {get;set;}
  DateTime PublishedDate {get;set;}
  ...
}

class TagNavigationPanelViewModel {
  string TagText {get;set;}
  int PostsCount {get;set;}
}

class CalendarNavigationPanelViewModel {
  DateTime YearAndMonth {get;set;}
  int PostsCount {get;set;} 
}

Minha pergunta é - como combinar bem essas visões parciais.

Hedin
fonte

Respostas:

1

Vejo outro método que, a menos que eu tenha entendido mal sua postagem, não foi mencionado:

A visão principal,, postteria seu modelo. Este modelo consistirá em SOMENTE as propriedades necessárias para exibir este post ( author, title, body, etc). Então, cada pedaço da postvisão de que você pode pensar ( timeline, tag navigation panel, subscribing panel, etc), seria dividido em suas próprias opiniões e cada um teria seu próprio modelo. Dessa forma, você pode criar esses modelos no seu controlador quando precisar deles.

Pode parecer uma quantidade desnecessária de trabalho extra para separá-los dessa maneira, mas se presta ao princípio da responsabilidade única . Mantenha cada "visão / modelo" focada em si mesma, para que possa ser reutilizada em qualquer lugar que seja necessário.

Se você achar que seu código está começando a se duplicar, o que pode depender da sua situação, considere escrever algum tipo de "classe auxiliar". Essa classe auxiliar lidaria com toda a construção do modelo em um único local, e todos os outros códigos duplicados seriam reduzidos a uma chamada de classe auxiliar.

ethorn10
fonte
Essa é uma abordagem geral que tento seguir. Minha pergunta era sobre como combinar essas visões parciais com modelos próprios. Ainda assim, eu atualizaria a pergunta para torná-la mais clara.
Hedin
1
Entendo ... desculpe pela confusão inicial. Eu aceitaria a visualização de contêiner que abriga todas as visualizações parciais necessárias, pessoalmente.
precisa saber é o seguinte
1

O que estou fazendo é uma variação / combinação dos seus pontos 1 e 3. Combino os modelos de exibição em uma classe de contêiner e o uso como modelo de exibição "principal". A passagem das peças como modelos para as parciais.

Seguindo o seu exemplo, eu criaria esse viewmodel para a página padrão:

class DefaultViewModel {
  public List<SinglePostViewModel> Posts ...
  public TagNavigationPanelViewModel Tags ...
  public CalendarNavigationPanelViewModel Calendar ...
  ...
}

Em Default.cshtml

@model DefaultViewModel
...html for rendering the default page...


@Html.Partial("_TagNavigationPanel", Model.Tags)
...etc...

Em _TagNavigationPanel.cshtml

@model TagNavigationPanelViewModel
...html+razor for rendering the tags...

Em seguida, siga a mesma abordagem para uma única página de postagem:

class SinglePostPageViewModel {
  public SinglePostViewModel Post ...
  // no tags in single view, for example..
  // public TagNavigationPanelViewModel Tags ...
  public CalendarNavigationPanelViewModel Calendar ...
  // But a list of related, perhaps?
  public List<RelatedPosts> RelatedPosts
  ...
}

E construa suas visualizações (cshtml (s)) de acordo

Lorenzo Dematté
fonte
É disso que trata uma abordagem. A terceira refere-se apenas à chamada RenderAction ou @ Html.Action, que envolve a chamada do método do controlador. Obrigado pela resposta!
Hedin
1
@ Hedin oh, ok ... Eu pensei que sua abordagem # 1 era mais "monolítica", com um grande modelo de exibição (diferente). Então, sim, eu uso 1 e acho bom. Eu também gosto menos do terceiro, mas é um bom cache de wrt. Se você tiver problemas de desempenho ou precisar armazenar partes da exibição em cache, pode valer a pena tentar.
Lorenzo Dematté 8/08
Que tal pular uma exibição parcial? por exemplo, com base na função de usuário?
LifeH2O
0

Você pode criar uma única exibição de "contêiner" com todas as três subvisões - SinglePostView, TagNavigationPanelViewe CalendarNavigationPanelView. Você também pode substituir o SinglePostViewpor qualquer outro modo de exibição exigido por uma página. Dessa forma, você só precisa substituir a exibição "central" (postagem) de páginas diferentes por outro tipo de exibição (por exemplo, lista de postagens) e as outras exibições precisam apenas ser atualizadas com os dados correspondentes, não substituídos.

A visualização do contêiner (por exemplo MyView) deve conter referências a todas as subvisões. Pode ter updatemétodos diferentes usados ​​para atualizar subvisões diferentes. Por exemplo - updateCalendar(CalendarNavigationPanelViewModel calendarData)ou updatePost(SinglePostViewModel postData). Ou até mesmo um update(IViewModel modelData)- você precisará verificar o tipo (e transmitir) o modelDatapara determinar qual visualização atualizar

stan0
fonte