asp.net-mvc - una - view component asp.net core
ASP.NET MVC: cómo usar exactamente View Models (3)
Digamos que tengo una página que permite editar los detalles de un usuario, así que tengo un ViewModel como este:
public class UserViewModel {
public string Username { get; set; }
public string Password { get; set; }
public int ManagerId { get; set; }
public string Category { get; set; }
}
Por lo tanto, en mi acción EditUser puedo hacer que el cuaderno modelo pase esto y luego puedo asignarlo al Modelo de dominio:
public ActionResult EditUser(UserViewModel user) {
...
Sin embargo, la página que muestra el formulario también necesita detalles tales como una lista de Administradores y Categorías para proporcionar listas desplegables para esos campos. También podría mostrar una lista de otros usuarios en una barra lateral para que pueda alternar entre los diferentes usuarios que está editando.
Entonces, tengo otro modelo de vista:
public class ViewUserViewModel {
public UserViewModel EditingUser { get; set; }
public IEnumerable<SelectListItem> Managers { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public IEnumerable<SelectListItem> AllUsers { get; set; }
}
¿Es esta la forma correcta de hacerlo? ¿Ambos son Modelos de Vista? Si es así, ¿existe una convención de nomenclatura que deba usar para poder distinguir entre máquinas virtuales que son como modelos y máquinas virtuales que solo contienen datos para la página?
¿Tengo todo esto mal?
"Ver modelo" es solo un patrón. No hay nada mágico en el nombre, pero generalmente cualquier clase que se pase a una vista (ya sea para simplemente mostrar datos o para envíos de formularios) se conoce como "modelo de vista" y se le da un nombre como FooViewModel
o FooVM
para indicar que es parte de ese patrón de "ver modelo".
No quiero ser demasiado filosófico contigo, pero creo que un poco de referencia sobre los patrones en juego será útil. ASP.NET MVC obviamente fomenta un modelo arquitectónico MVC (Modelo-Vista-Controlador). En MVC, el Modelo es el contenedor de toda la lógica comercial de la aplicación. El controlador es responsable de manejar la solicitud, obtener el modelo, renderizar la vista con ese modelo y devolver una respuesta. Parece una gran responsabilidad, pero en realidad el framework maneja la mayor parte de esto detrás de escena, por lo que los Controladores son típicamente (y deberían ser) muy livianos en el código. Son responsables de la cantidad mínima de funcionalidad para conectar todo. Finalmente, View es responsable de crear la capa UI que le permite al usuario interactuar con los datos en el Modelo. No es responsable de los datos en sí, ni debería ser (ViewData / ViewBag es una violación bastante grande aquí, al menos en la medida en que los desarrolladores la utilizan en la práctica).
Entonces, eso significa que la mayor parte de la lógica de su aplicación debe estar en su modelo, y generalmente eso es algo bueno. Sin embargo, dado que el modelo es el refugio de datos de aplicaciones, generalmente persiste en una base de datos o similar. Eso crea cierto conflicto de intereses ya que ahora necesita comenzar un acto de equilibrio entre los datos que deben conservarse y los datos que solo deberían existir para mostrarlos.
Aquí es donde entran los modelos de vista. MVVM (Model-View-View Model), un patrón algo paralelo a MVC, reconoce los problemas inherentes en un enfoque de un modelo a otro. No entraré en muchos detalles aquí, porque MVC no usa este patrón. Sin embargo, la mayoría de los desarrolladores de ASP.NET MVC han elegido el Modelo de Vista de MVVM. Lo que esencialmente se obtiene es una entidad respaldada por una base de datos (el modelo tradicional) y generalmente muchos modelos de vista diferentes que representan esa entidad en varios estados. Esto permite que su modelo contenga la lógica de negocio que es relevante para la persistencia, mientras que los modelos de vista contienen la lógica empresarial relevante para mostrar, crear y actualizar ese modelo.
Me he desviado un poco, pero lo largo y lo corto es que lo que estás haciendo es perfectamente aceptable. De hecho, es una buena práctica. Cree tantos modelos de vista como requiera su aplicación, y úselos para almacenar realmente los datos y la lógica de negocios necesarios para sus vistas. (Eso incluye cosas como SelectList
s. Ni su controlador ni su vista deberían necesitar saber cómo crear una SelectList
de SelectList
para un menú desplegable).
Cómo hago esto en atajo:
- Cree una clase separada de ViewModel para cada formulario en la página, luego renderizo estas clases con PartialViews como
@{Html.RenderPartial("PartialName", Model.PartialModel);}
. - Si la página contiene cosas como html metas, hago una clase separada para metas y la pongo en la sección de la página.
- Los casos de descanso como "¿Debería poner esto en clases separadas?" es tu juicio
Entonces, por ejemplo, tiene una página que tiene algún tipo de barra de inicio de sesión / registro o ventana emergente.
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<SelectListItem> 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))
<input type="submit" value="Update" />
}
}
@section Metas {
@{Html.RenderPartial("Meatas", Model.Metas}
}
Acerca de las plantillas de editor Brad Wilsons Blog y solo busca en Google o apila recursos sobre plantillas de visualización / editor y HtmlHelpers. Todos son muy útiles para construir sitios web coherentes.
Personalmente prefiero presentar toda la información requerida para que la página se represente en ViewModel, ya que es el objetivo de ViewModel: proporcionar todos los datos para la Vista. Así que mi UserViewModel
contendría propiedades para Managers
, Categories
y AllUsers
y el controlador llenaría esas colecciones antes de pasar el ViewModel a la vista.
Esto es esencialmente lo que ha hecho, simplemente elimina el ViewModel adicional de la ecuación.
También he visto a otros programadores usar ViewData para enviar las listas desplegables a la vista, pero no me gusta porque ViewData no está fuertemente tipado, mientras que ViewModel sí lo está.