Edit: j'ai mis à jour cette réponse sur mon blog:
http://www.samwheat.com/post/The-function-of-ViewModels-in-MVC-web-development
Ma réponse est un peu longue mais je pense qu'il est important de comparer les modèles de vue à d'autres types de modèles couramment utilisés pour comprendre pourquoi ils sont différents et pourquoi ils sont nécessaires.
Pour résumer et répondre directement à la question posée:
De manière générale, un modèle de vue est un objet qui contient toutes les propriétés et méthodes nécessaires pour rendre une vue. Les propriétés du modèle de vue sont souvent liées à des objets de données tels que les clients et les commandes et, en outre, elles contiennent également des propriétés liées à la page ou à l'application elle-même, telles que le nom d'utilisateur, le nom de l'application, etc. Les modèles de vue fournissent un objet pratique à transmettre à un moteur de rendu. créer une page html. L'une des nombreuses raisons d'utiliser un modèle de vue est que les modèles de vue fournissent un moyen de tester à l'unité certaines tâches de présentation telles que la gestion des entrées utilisateur, la validation des données, la récupération des données pour l'affichage, etc.
Voici une comparaison des modèles Entity (a.ka. DTO's a.ka. models), Presentation Models et View Models.
Objets de transfert de données alias «modèle»
Un objet de transfert de données (DTO) est une classe dont les propriétés correspondent à un schéma de table dans une base de données. Les DTO sont nommés pour leur utilisation courante pour la navette de données vers et depuis un magasin de données.
Caractéristiques des DTO:
• Sont des objets métier - leur définition dépend des données d'application.
• Ne contiennent généralement que des propriétés - pas de code.
• Principalement utilisé pour transporter des données vers et depuis une base de données.
• Les propriétés correspondent exactement ou étroitement aux champs d'une table spécifique dans un magasin de données.
Les tables de base de données sont généralement normalisées, les DTO sont donc également normalisés. Cela les rend d'une utilité limitée pour la présentation des données. Cependant, pour certaines structures de données simples, elles fonctionnent souvent assez bien.
Voici deux exemples de ce à quoi pourraient ressembler les 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; }
}
Modèles de présentation
Un modèle de présentation est une classe utilitaire utilisée pour afficher des données sur un écran ou un rapport. Les modèles de présentation sont généralement utilisés pour modéliser des structures de données complexes composées de données provenant de plusieurs DTO. Les modèles de présentation représentent souvent une vue dénormalisée des données.
Caractéristiques des modèles de présentation:
• Sont des objets métier - leur définition dépend des données d'application.
• Contiennent principalement des propriétés. Le code est généralement limité au formatage des données ou à la conversion vers ou depuis un DTO. Les modèles de présentation ne doivent pas contenir de logique métier.
• Présentent souvent une vue dénormalisée des données. Autrement dit, ils combinent souvent les propriétés de plusieurs DTO.
• Contiennent souvent des propriétés d'un type de base différent de celui d'un DTO. Par exemple, les montants en dollars peuvent être représentés sous forme de chaînes afin qu'ils puissent contenir des virgules et un symbole monétaire.
• Souvent définis par la façon dont ils sont utilisés ainsi que par les caractéristiques de leur objet. En d'autres termes, un DTO simple utilisé comme modèle de support pour le rendu d'une grille est en fait également un modèle de présentation dans le contexte de cette grille.
Les modèles de présentation sont utilisés «selon les besoins» et «si nécessaire» (alors que les DTO sont généralement liés au schéma de la base de données). Un modèle de présentation peut être utilisé pour modéliser des données pour une page entière, une grille sur une page ou une liste déroulante sur une grille sur une page. Les modèles de présentation contiennent souvent des propriétés qui sont d'autres modèles de présentation. Les modèles de présentation sont souvent construits dans un but à usage unique, comme rendre une grille spécifique sur une seule page.
Un exemple de modèle de présentation:
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); } }
}
Voir les modèles
Un modèle de vue est similaire à un modèle de présentation dans la mesure où il s'agit d'une classe de support pour le rendu d'une vue. Cependant, il est très différent d'un modèle de présentation ou d'un DTO dans la façon dont il est construit. Les modèles de vue contiennent souvent les mêmes propriétés que les modèles de présentation et les DTO et, pour cette raison, ils sont souvent confondus l'un avec l'autre.
Caractéristiques des modèles de vue:
• Sont la seule source de données utilisée pour rendre une page ou un écran. Cela signifie généralement qu'un modèle de vue exposera toutes les propriétés dont tout contrôle de la page aura besoin pour s'afficher correctement. Faire du modèle de vue la source unique de données pour la vue améliore considérablement sa capacité et sa valeur pour les tests unitaires.
• Sont des objets composites qui contiennent des propriétés constituées de données d'application ainsi que des propriétés utilisées par le code d'application. Cette caractéristique est cruciale lors de la conception du modèle de vue pour la réutilisabilité et est discutée dans les exemples ci-dessous.
• Contient le code d'application. Les modèles de vue contiennent généralement des méthodes qui sont appelées pendant le rendu et lorsque l'utilisateur interagit avec la page. Ce code concerne généralement la gestion des événements, l'animation, la visibilité des contrôles, le style, etc.
• Contenir du code qui appelle des services commerciaux dans le but de récupérer des données ou de les envoyer à un serveur de base de données. Ce code est souvent placé par erreur dans un contrôleur. L'appel de services métier à partir d'un contrôleur limite généralement l'utilité du modèle d'affichage pour les tests unitaires. Pour être clair, les modèles de vue eux-mêmes ne doivent pas contenir de logique métier mais doivent appeler des services qui contiennent une logique métier.
• Contiennent souvent des propriétés qui sont d'autres modèles de vue pour d'autres pages ou écrans.
• Sont écrits «par page» ou «par écran». Un modèle de vue unique est généralement écrit pour chaque page ou écran d'une application.
• Dérivent généralement d'une classe de base car la plupart des pages et écrans partagent des propriétés communes.
Voir la composition du modèle
Comme indiqué précédemment, les modèles de vue sont des objets composites dans la mesure où ils combinent les propriétés d'application et les propriétés de données métier sur un seul objet. Voici des exemples de propriétés d'application couramment utilisées sur les modèles de vue:
• Propriétés utilisées pour afficher l'état de l'application, telles que les messages d'erreur, le nom d'utilisateur, l'état, etc.
• Propriétés utilisées pour formater, afficher, styliser ou animer des contrôles.
• Propriétés utilisées pour la liaison de données, telles que les objets de liste et les propriétés qui contiennent des données intermédiaires entrées par l'utilisateur.
Les exemples suivants montrent pourquoi la nature composite des modèles de vue est importante et comment nous pouvons construire au mieux un modèle de vue efficace et réutilisable.
Supposons que nous écrivons une application Web. L'une des exigences de la conception de l'application est que le titre de la page, le nom d'utilisateur et le nom de l'application doivent être affichés sur chaque page. Si nous voulons créer une page pour afficher un objet d'ordre de présentation, nous pouvons modifier le modèle de présentation comme suit:
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); } }
}
Cette conception pourrait fonctionner… mais que se passe-t-il si nous voulons créer une page qui affichera une liste de commandes? Les propriétés PageTitle, UserName et ApplicationName seront répétées et deviendront difficiles à utiliser. Et si nous voulons définir une logique de niveau page dans le constructeur de la classe? Nous ne pouvons plus le faire si nous créons une instance pour chaque commande qui sera affichée.
Composition sur héritage
Voici une façon dont nous pourrions re-factoriser le modèle de présentation des commandes de sorte qu'il devienne un véritable modèle de vue et sera utile pour afficher un seul objet PresentationOrder ou une collection d'objets 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; }
}
En regardant les deux classes ci-dessus, nous pouvons voir qu'une façon de penser à un modèle de vue est qu'il s'agit d'un modèle de présentation qui contient un autre modèle de présentation en tant que propriété. Le modèle de présentation de niveau supérieur (c'est-à-dire le modèle de vue) contient des propriétés pertinentes pour la page ou l'application tandis que le modèle de présentation (propriété) contient des propriétés pertinentes pour les données d'application.
Nous pouvons aller plus loin dans notre conception et créer une classe de modèle de vue de base qui peut être utilisée non seulement pour PresentationOrders, mais également pour toute autre classe:
public class BaseViewModel
{
// Application properties
public string PageTitle { get; set; }
public string UserName { get; set; }
public string ApplicationName { get; set; }
}
Maintenant, nous pouvons simplifier notre PresentationOrderVM comme ceci:
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public PresentationOrder Order { get; set; }
}
public class PresentationOrderVM : BaseViewModel
{
// Business properties
public List<PresentationOrder> Orders { get; set; }
}
Nous pouvons rendre notre BaseViewModel encore plus réutilisable en le rendant générique:
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; }
}
Maintenant, nos implémentations sont sans effort:
public class PresentationOrderVM : BaseViewModel<PresentationOrder>
{
// done!
}
public class PresentationOrderVM : BaseViewModel<List<PresentationOrder>>
{
// done!
}