A partir dessa pergunta , parece que faz sentido que um controlador crie um ViewModel que reflita com mais precisão o modelo que a visualização está tentando exibir, mas estou curioso sobre algumas das convenções (sou novo no padrão MVC , se já não era óbvio).
Basicamente, eu tinha as seguintes perguntas:
- Eu normalmente gosto de ter uma classe / arquivo. Isso faz sentido com um ViewModel se ele estiver sendo criado apenas para transferir dados de um controlador para uma exibição?
- Se um ViewModel pertence ao seu próprio arquivo e você está usando uma estrutura de diretório / projeto para manter as coisas separadas, a que lugar pertence o arquivo ViewModel ? No diretório Controladores ?
É basicamente isso por enquanto. Talvez eu tenha mais algumas perguntas, mas isso está me incomodando há mais ou menos uma hora, e consigo encontrar orientações consistentes em outros lugares.
EDIT: Olhando para o exemplo de aplicativo NerdDinner no CodePlex, parece que os ViewModels fazem parte dos Controladores , mas ainda me sinto desconfortável por não estarem em seus próprios arquivos.
asp.net-mvc
asp.net-mvc-viewmodel
jerhinesmith
fonte
fonte
Respostas:
Eu crio o que chamo de "ViewModel" para cada exibição. Coloquei-os em uma pasta chamada ViewModels no meu projeto da Web MVC. Eu os nomeio após o controlador e a ação (ou exibição) que eles representam. Portanto, se eu precisar passar dados para a visualização SignUp no controlador Membership, crio uma classe MembershipSignUpViewModel.cs e a coloco na pasta ViewModels.
Em seguida, adiciono as propriedades e métodos necessários para facilitar a transferência de dados do controlador para a visualização. Eu uso o Automapper para ir do meu ViewModel para o modelo de domínio e voltar, se necessário.
Isso também funciona bem para os ViewModels compostos que contêm propriedades do tipo de outros ViewModels. Por exemplo, se você possui 5 widgets na página de índice no controlador de associação e criou um ViewModel para cada visualização parcial - como você passa os dados da ação Index para as parciais? Você adiciona uma propriedade ao MembershipIndexViewModel do tipo MyPartialViewModel e ao renderizar o parcial você passaria em Model.MyPartialViewModel.
Fazer isso dessa maneira permite ajustar as propriedades parciais do ViewModel sem precisar alterar a exibição do Índice. Ele ainda passa no Model.MyPartialViewModel, então há menos chances de você ter que passar por toda a cadeia de parciais para corrigir algo quando tudo o que você está fazendo é adicionar uma propriedade ao ViewModel parcial.
Também adicionarei o espaço de nome "MyProject.Web.ViewModels" ao web.config para permitir que eu os faça referência em qualquer modo de exibição sem nunca adicionar uma declaração de importação explícita em cada modo de exibição. Apenas torna um pouco mais limpo.
fonte
Separar classes por categoria (controladores, modelos de exibição, filtros etc.) não faz sentido.
Se você deseja escrever um código para a seção Inicial do seu site (/), crie uma pasta chamada Home e coloque lá o HomeController, IndexViewModel, AboutViewModel, etc. e todas as classes relacionadas usadas pelas ações da Página inicial.
Se você compartilhou classes, como um ApplicationController, pode colocá-lo na raiz do seu projeto.
Por que separar as coisas que estão relacionadas (HomeController, IndexViewModel) e manter as coisas juntas que não têm nenhuma relação (HomeController, AccountController)?
Eu escrevi um post sobre este tópico.
fonte
Eu mantenho minhas classes de aplicativos em uma subpasta chamada "Core" (ou uma biblioteca de classes separada) e uso os mesmos métodos que o aplicativo de amostra KIGG , mas com algumas pequenas alterações para tornar meus aplicativos mais SECA.
Crio uma classe BaseViewData em / Core / ViewData / onde armazeno propriedades comuns em todo o site.
Depois disso, também crio todas as minhas classes de ViewData de exibição na mesma pasta que derivam de BaseViewData e têm propriedades específicas de exibição.
Em seguida, crio um ApplicationController do qual todos os meus controladores derivam. O ApplicationController possui um método GetViewData genérico da seguinte maneira:
Finalmente, na minha ação do Controller, faço o seguinte para criar meu modelo ViewData
Eu acho que isso funciona muito bem e mantém suas opiniões organizadas e seus controladores magros.
fonte
Uma classe ViewModel existe para encapsular várias partes de dados representadas por instâncias de classes em um objeto fácil de gerenciar que você pode passar para o seu View.
Seria bom ter suas classes ViewModel em seus próprios arquivos, no próprio diretório. Nos meus projetos, tenho uma subpasta da pasta Modelos chamada ViewModels. É aí que meus ViewModels (por exemplo
ProductViewModel.cs
) moram.fonte
Não há um bom lugar para manter seus modelos. Você pode mantê-los em montagem separada se o projeto for grande e houver muitos ViewModels (Data Transfer Objects). Além disso, você pode mantê-los em uma pasta separada do projeto do site. Por exemplo, no Oxite, eles são colocados no projeto Oxite, que também contém várias classes. Os controladores da Oxite são movidos para um projeto separado e as visualizações também estão em um projeto separado.
No CodeCampServer, os modelos de vista são nomeados * Form e são colocados no projeto de interface do usuário na pasta Modelos.
No projeto MvcPress , eles são colocados no projeto Data, que também contém todo o código para trabalhar com o banco de dados e um pouco mais (mas eu não recomendei essa abordagem, é apenas uma amostra)
Então você pode ver que existem muitos pontos de vista. Normalmente mantenho meus ViewModels (objetos DTO) no projeto do site. Mas quando tenho mais de 10 modelos, prefiro movê-los para montagem separada. Normalmente, neste caso, também estou movendo os controladores para a montagem separada.
Outra questão é como mapear facilmente todos os dados do modelo para o seu ViewModel. Sugiro dar uma olhada na biblioteca do AutoMapper . Eu gosto muito, faz todo o trabalho sujo para mim.
E também sugiro olhar para o projeto SharpArchitecture . Ele fornece uma arquitetura muito boa para projetos e contém muitos frameworks e orientações interessantes e ótima comunidade.
fonte
aqui está um trecho de código das minhas práticas recomendadas:
fonte
Lançamos todos os nossos ViewModels na pasta Modelos (toda a nossa lógica de negócios está em um projeto separado do ServiceLayer)
fonte
Pessoalmente, sugiro que, se o ViewModel não for trivial, use uma classe separada.
Se você tiver mais de um modelo de visualização, sugiro que faça sentido particioná-lo em pelo menos um diretório. se o modelo de vista for compartilhado posteriormente, o espaço para nome implícito no diretório facilita a mudança para um novo assembly.
fonte
No nosso caso, temos os modelos junto com os controladores em um projeto separado das vistas.
Como regra geral, tentamos mover e evitar a maioria das coisas do ViewData ["..."] para o ViewModel, para evitar castings e seqüências de caracteres mágicas, o que é uma coisa boa.
O ViewModel também possui algumas propriedades comuns, como informações de paginação para listas ou informações de cabeçalho da página para desenhar migalhas de pão e títulos. Nesse momento, a classe base contém muitas informações em minha opinião e podemos dividi-las em três partes, as informações mais básicas e necessárias para 99% das páginas em um modelo de vista base e, em seguida, um modelo para as listas e um modelo para os formulários que contêm dados específicos para esses cenários e herdam do base.
Por fim, implementamos um modelo de visualização para cada entidade para lidar com as informações específicas.
fonte
código no controlador:
código no modelo de exibição:
projetos:
DevJet.Web (o projeto da Web ASP.NET MVC)
DevJet.Web.App.Dictionary (um projeto de biblioteca de classes separado)
Neste projeto, criei algumas pastas como: DAL, BLL, BO, VM (pasta para modelos de exibição)
fonte
Crie uma classe base de modelo de exibição que possua propriedades normalmente necessárias, como resultado da operação e dados contextuais, você também pode colocar dados e funções atuais do usuário
Na classe do controlador base, existe um método como PopulateViewModelBase (), esse método preencherá os dados contextuais e as funções do usuário. O HasError e o ErrorMessage, defina essas propriedades se houver exceção ao extrair dados do service / db. Ligue essas propriedades na exibição para mostrar erro. As funções de usuário podem ser usadas para mostrar a seção ocultar na exibição com base nas funções.
Para preencher modelos de exibição em diferentes ações get, é possível torná-lo consistente com o controlador base com o método abstrato FillModel
Nos controladores
fonte