ASP.net MVC – como exatamente usar modelos de exibição

Digamos que eu tenha uma página que permita a edição dos detalhes de um usuário, então eu tenho um ViewModel assim:

public class UserViewModel { public string Username { get; set; } public string Password { get; set; } public int ManagerId { get; set; } public string Category { get; set; } } 

Então, na minha ação EditUser, posso ter isso passado de volta pelo fichário do modelo e, em seguida, posso mapear isso para o Modelo de Domínio:

 public ActionResult EditUser(UserViewModel user) { ... 

No entanto, a página que exibe o formulário também precisa de detalhes, como uma lista de gerentes e categorias, para fornecer menus suspensos para esses campos. Ele também pode exibir uma lista de outros usuários em uma barra lateral para que você possa alternar entre os diferentes usuários que você está editando.

Então eu tenho outro modelo de visão:

 public class ViewUserViewModel { public UserViewModel EditingUser { get; set; } public IEnumerable Managers { get; set; } public IEnumerable Categories { get; set; } public IEnumerable AllUsers { get; set; } } 

Esta é a maneira correta de fazer isso? Ambos são modelos de exibição? Em caso afirmativo, existe uma convenção de nomenclatura que eu deveria usar para que eu possa distinguir entre VMs que são como modelos e VMs que contêm apenas dados para a página?

Eu entendi tudo errado?

Como faço isso no atalho:

  1. Crie uma class ViewModel separada para cada formulário na página e, em seguida, eu renderizo essas classs com o PartialViews como @{Html.RenderPartial("PartialName", Model.PartialModel);} .
  2. Se a página contém coisas como metas de html eu faço classs separadas para metas e coloco em seção na página.
  3. Restos casos como “eu deveria colocar isso em class separada?” é o seu julgamento.

Então, por exemplo, você tem uma página que tem algum tipo de barra de login / registro ou popup.

 public class SomePageViewModel { public RegisterBarVM Register { get; set; } public LoginBarVM LoginBar { get; set; } public MetasVM Metas { get; set; } public string MaybePageTitle { get; set;} public string MaybePageContent { get; set;} [HiddenInput(DisplayValue = false)] public int IdIfNeeded { get; set; } public IEnumerable SomeItems {get; set;} public string PickedItemId { get;set; } } public class RegisterBarVM { public string RegisterUsername {get;set;} public string RegisterPassword {get;set;} //... } public class LoginBarVM { public string LoginUserame {get;set;} public string LoginPassword {get;set;} //... } //cshtml @model yourClassesNamespace.SomePageViewModel @{ Html.RenderPartial("LoginBar", Model.LoginBar); //form inside Html.RenderPartial("RegisterBar", Model.RegisterBar); //form inside using(Html.BeginForm()) { @Html.EditorFor(m => m.IdIfNeeded) @Hmtl.EditorFor(m => m.MaybePageTitle) @Hmtl.EditorFor(m => m.MaybePageContent) @Hmtl.DropDownListFor(m => m.PickedItemId, new SelectList(Model.SomeItems))  } } @section Metas { @{Html.RenderPartial("Meatas", Model.Metas} } 

Sobre modelos de editor Brad Wilsons Blog e apenas google ou procurar resources de pilhas sobre modelos de exibição / editor e HtmlHelpers. Todos eles são muito úteis para construir sites consistentes.

“View Model” é apenas um padrão. Não há nada mágico sobre o nome, mas geralmente qualquer class passada para uma exibição (seja simplesmente exibindo dados ou para fins de submissão de formulários) é chamada de “modelo de exibição” e recebe um nome como FooViewModel ou FooVM para indicar que faz parte do padrão “view model”.

Eu não quero ir muito filosófico em você, mas acho que um pouco de referência sobre os padrões em jogo será útil. O ASP.NET MVC obviamente incentiva um modelo arquitetural MVC (Model-View-Controller). No MVC, o Modelo é o contêiner para toda a lógica de negócios do aplicativo. O Controlador é responsável por manipular o pedido, buscar o modelo, renderizar o View com esse modelo e retornar uma resposta. Isso parece muita responsabilidade, mas na verdade o framework lida com a maior parte dos bastidores, então os controladores são tipicamente (e devem ser) muito leves no código. Eles são responsáveis ​​pelo mínimo de funcionalidade para conectar tudo. Finalmente, o View é responsável por criar a camada de interface do usuário que permite ao usuário interagir com os dados no modelo. Ele não é responsável pelos dados em si, nem deve ser (ViewData / ViewBag é uma violação muito grande aqui, pelo menos na medida em que acaba sendo usado pelos desenvolvedores na prática).

Então, isso significa que a maior parte da lógica do seu aplicativo deve estar no seu modelo e, normalmente, isso é bom. No entanto, como o modelo é o refúgio dos dados do aplicativo, ele geralmente é persistido em um database ou similar. Isso cria algum conflito de interesses, já que agora é necessário iniciar um ato de equilíbrio entre quais dados devem ser mantidos e quais dados devem existir apenas para fins de exibição.

É aí que entram os modelos de visualização. O MVVM (Model-View-View Model), um padrão paralelo ao MVC, reconhece os problemas inerentes à abordagem de um modelo para regra-para-todos. Não vou entrar em muitos detalhes aqui, porque o MVC não usa esse padrão. No entanto, a maioria dos desenvolvedores ASP.NET MVC cooptaram o View Model do MVVM. O que você essencialmente conclui é uma entidade com base em database (o modelo tradicional) e, em seguida, geralmente muitos modelos de exibição diferentes que representam essa entidade em vários estados. Isso permite que seu modelo contenha a lógica de negócios relevante à persistência, enquanto os modelos de visualização contêm a lógica de negócios relevante para exibir, criar e atualizar esse modelo.

Eu saí um pouco da pista, mas o longo e o curto é que o que você está fazendo é perfeitamente aceitável. Na verdade, é uma boa prática. Crie quantos modelos de visualização forem necessários e use-os para armazenar os dados e a lógica de negócios necessários para suas visualizações. (Isso inclui coisas como SelectList s. Nem o seu controlador nem visão deve precisar saber como criar um SelectList para uma lista suspensa.)

Eu pessoalmente prefiro colocar todas as informações necessárias para a página renderizar no ViewModel, já que esse é o propósito do ViewModel – fornecer todos os dados para o View. Portanto, meu UserViewModel conteria propriedades para Managers , Categories e AllUsers e o controlador preencheria essas collections antes de passar o ViewModel para a exibição.

Isto é essencialmente o que você fez – apenas remove o ViewModel extra da equação.

Eu também vi outros programadores usarem o ViewData para enviar as listas suspensas para a view, mas eu não gosto disso porque o ViewData não é fortemente tipado, enquanto o ViewModel é.