Editar: Actualicé esta respuesta en mi Blog:
http://www.samwheat.com/post/The-function-of-ViewModels-in-MVC-web-development
Mi respuesta es un poco larga, pero creo que es importante comparar los modelos de vista con otros tipos de modelos de uso común para comprender por qué son diferentes y por qué son necesarios.
Para resumir y responder directamente a la pregunta que se hace:
En términos generales, un modelo de vista es un objeto que contiene todas las propiedades y métodos necesarios para representar una vista. Las propiedades del modelo de vista a menudo están relacionadas con objetos de datos, como clientes y pedidos, y además contienen propiedades relacionadas con la página o la aplicación en sí, como el nombre de usuario, el nombre de la aplicación, etc. Los modelos de vista proporcionan un objeto conveniente para pasar a un motor de renderizado. crear una página html Una de las muchas razones para usar un modelo de vista es que los modelos de vista proporcionan una forma de probar unitariamente ciertas tareas de presentación, como manejar la entrada del usuario, validar datos, recuperar datos para mostrar, etc.
Aquí hay una comparación de los modelos de entidad (también conocidos como modelos DTO), modelos de presentación y modelos de vista.
Objetos de transferencia de datos, también conocido como "Modelo"
Un objeto de transferencia de datos (DTO) es una clase con propiedades que coinciden con un esquema de tabla en una base de datos. Los DTO se nombran por su uso común para transferir datos hacia y desde un almacén de datos.
Características de los DTO:
• Son objetos comerciales: su definición depende de los datos de la aplicación.
• Por lo general, solo contienen propiedades, sin código.
• Se utiliza principalmente para transportar datos hacia y desde una base de datos.
• Las propiedades coinciden exacta o estrechamente con los campos de una tabla específica en un almacén de datos.
Las tablas de la base de datos generalmente se normalizan, por lo tanto, los DTO también se normalizan. Esto los hace de uso limitado para presentar datos. Sin embargo, para ciertas estructuras de datos simples, a menudo funcionan bastante bien.
Aquí hay dos ejemplos de cómo se verían los DTO:
public class Customer
{
public int ID { get; set; }
public string CustomerName { get; set; }
}
public class Order
{
public int ID { get; set; }
public int CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public Decimal OrderAmount { get; set; }
}
Modelos de presentación
Un modelo de presentación es una utilidad. clase de que se utiliza para representar datos en una pantalla o informe. Los modelos de presentación generalmente se usan para modelar estructuras de datos complejas que se componen de datos de múltiples DTO. Los modelos de presentación a menudo representan una vista desnormalizada de datos.
Características de los modelos de presentación:
• Son objetos comerciales: su definición depende de los datos de la aplicación.
• Contienen principalmente propiedades. El código generalmente se limita a formatear datos o convertir ao desde un DTO. Los modelos de presentación no deben contener lógica empresarial.
• A menudo presentan una vista desnormalizada de datos. Es decir, a menudo combinan propiedades de múltiples DTO.
• A menudo contienen propiedades de un tipo base diferente que un DTO. Por ejemplo, los montos en dólares pueden representarse como cadenas para que puedan contener comas y un símbolo de moneda.
• A menudo se define por cómo se usan, así como por sus características de objeto. En otras palabras, un DTO simple que se utiliza como modelo de respaldo para representar una cuadrícula es, de hecho, también un modelo de presentación en el contexto de esa cuadrícula.
Los modelos de presentación se usan "según sea necesario" y "donde sea necesario" (mientras que los DTO generalmente están vinculados al esquema de la base de datos). Se puede usar un modelo de presentación para modelar datos para una página completa, una cuadrícula en una página o un menú desplegable en una cuadrícula en una página. Los modelos de presentación a menudo contienen propiedades que son otros modelos de presentación. Los modelos de presentación a menudo se construyen para un propósito de un solo uso, como representar una cuadrícula específica en una sola página.
Un ejemplo de modelo de presentación:
public class PresentationOrder
{
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
public string CustomerName { get; set; }
public Decimal OrderAmount { get; set; }
public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}
Ver modelos
Un modelo de vista es similar a un modelo de presentación, ya que es una clase de respaldo para representar una vista. Sin embargo, es muy diferente de un Modelo de Presentación o un DTO en cuanto a cómo se construye. Los modelos de vista a menudo contienen las mismas propiedades que los modelos de presentación y los DTO y, por esta razón, a menudo se confunden uno con el otro.
Características de los modelos de vista:
• Son la única fuente de datos utilizada para representar una página o pantalla. Por lo general, esto significa que un modelo de vista expondrá cada propiedad que cualquier control en la página necesitará para representarse correctamente. Hacer que el modelo de vista sea la única fuente de datos para la vista mejora en gran medida su capacidad y valor para las pruebas unitarias.
• Son objetos compuestos que contienen propiedades que consisten en datos de la aplicación, así como propiedades que utiliza el código de la aplicación. Esta característica es crucial al diseñar el modelo de vista para su reutilización y se discute en los ejemplos a continuación.
• Contiene el código de la aplicación. Los modelos de vista generalmente contienen métodos que se invocan durante la representación y cuando el usuario interactúa con la página. Este código generalmente se relaciona con el manejo de eventos, la animación, la visibilidad de los controles, el estilo, etc.
• Contener código que llame a servicios comerciales con el propósito de recuperar datos o enviarlos a un servidor de base de datos. Este código a menudo se coloca por error en un controlador. Llamar a los servicios comerciales desde un controlador generalmente limita la utilidad del modelo de vista para pruebas unitarias. Para ser claros, los modelos de vista en sí mismos no deben contener lógica empresarial, sino que deben realizar llamadas a servicios que sí contienen lógica empresarial.
• A menudo contienen propiedades que son otros modelos de vista para otras páginas o pantallas.
• Están escritos "por página" o "por pantalla". Por lo general, se escribe un modelo de vista único para cada página o pantalla de una aplicación.
• Generalmente derivan de una clase base ya que la mayoría de las páginas y pantallas comparten propiedades comunes.
Ver composición del modelo
Como se indicó anteriormente, los modelos de vista son objetos compuestos en el sentido de que combinan propiedades de aplicación y propiedades de datos comerciales en un solo objeto. Los ejemplos de propiedades de aplicación de uso común que se usan en los modelos de vista son:
• Propiedades que se utilizan para mostrar el estado de la aplicación, como mensajes de error, nombre de usuario, estado, etc.
• Propiedades utilizadas para formatear, mostrar, estilizar o animar controles.
• Propiedades utilizadas para el enlace de datos, como objetos de lista y propiedades que contienen datos intermedios que ingresa el usuario.
Los siguientes ejemplos muestran por qué la naturaleza compuesta de los modelos de vista es importante y cómo podemos construir mejor un Modelo de vista que sea eficiente y reutilizable.
Supongamos que estamos escribiendo una aplicación web. Uno de los requisitos del diseño de la aplicación es que el título de la página, el nombre de usuario y el nombre de la aplicación se deben mostrar en cada página. Si queremos crear una página para mostrar un objeto de orden de presentación, podemos modificar el modelo de presentación de la siguiente manera:
public class PresentationOrder
{
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
public int OrderID { get; set; }
public DateTime OrderDate { get; set; }
public string PrettyDate { get { return OrderDate.ToShortDateString(); } }
public string CustomerName { get; set; }
public Decimal OrderAmount { get; set; }
public string PrettyAmount { get { return string.Format("{0:C}", OrderAmount); } }
}
Este diseño podría funcionar ... pero ¿qué pasa si queremos crear una página que muestre una lista de pedidos? Las propiedades PageTitle, UserName y ApplicationName se repetirán y serán difíciles de manejar. Además, ¿qué pasa si queremos definir alguna lógica a nivel de página en el constructor de la clase? Ya no podemos hacer eso si creamos una instancia para cada pedido que se mostrará.
Composición sobre herencia
Aquí hay una manera en que podríamos re-factorizar el modelo de presentación de orden de modo que se convierta en un modelo de vista real y sea útil para mostrar un solo objeto PresentationOrder o una colección de objetos PresentationOrder:
public class PresentationOrderVM
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
Mirando las dos clases anteriores, podemos ver que una forma de pensar sobre un modelo de vista es que es un modelo de presentación que contiene otro modelo de presentación como una propiedad. El modelo de presentación de nivel superior (es decir, el modelo de vista) contiene propiedades que son relevantes para la página o la aplicación, mientras que el modelo de presentación (propiedad) contiene propiedades que son relevantes para los datos de la aplicación.
Podemos llevar nuestro diseño un paso más allá y crear una clase de modelo de vista base que se pueda usar no solo para PresentationOrders, sino también para cualquier otra clase:
public class BaseViewModel
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
}
Ahora podemos simplificar nuestro PresentationOrderVM así:
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
Podemos hacer que nuestro BaseViewModel sea aún más reutilizable haciéndolo genérico:
public class BaseViewModel<T>
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
// Business property
public T BusinessObject { get; set; }
}
Ahora nuestras implementaciones son fáciles:
public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
// done!
}
public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
// done!
}