Où convertir un DTO en ViewModel?
j'ai hérité d'un projet MVC2 en utilisant un modèle de DDD assez standard et bien conservé. J'ai fait beaucoup de lecture sur l'ensemble du débat DTO/ViewModel ainsi.
Actuellement, nos Dto sont souvent utilisés comme Viewmodel. Honnêtement, cela ne fait aucune différence pour ce que nous faisons, mais j'aimerais utiliser des modèles de vue appropriés pendant que nous améliorons le site.
Voici ma question:
les modèles de notre projet" domaine" retiens les entités et rends les DTO à mes contrôleurs. Maintenant, je dois mapper ce DTO à un modèle de vue. Où dois-je le faire?
- Droit dans le contrôleur?
- dans le projet de domaine?
- d'Ailleurs?
je garde mes modèles de vue à côté des vues de notre projet "Web" pour qu'il se sente mal de convertir DTO -> ViewModel dans le domaine du projet. Il se sent également mal de le faire dans le contrôleur.
Ce qui d'autres ont-ils fait?
Edit:
Cette question/réponse suggère de le manipuler dans le contrôleur. C'est sûr qu'il devient facile de réfléchir à cela.
4 réponses
les DTO sont typiquement spécifiques à une technologie. Par exemple, dans le monde. NET, vos Dto sont probablement décorés avec DataContract
et DataMember
attributs de la sérialisation. De plus, les DTO et le service qui les renvoie forment un adaptateur au domaine en termes de architecture hexagonale. Ils adapter votre domaine à une technologie de transport spécifique telle que HTTP et en tant que telle ils vivent en dehors de votre domaine. En d'autres termes, le domaine ne devrait pas avoir connaissance de l' BDD - les BDD doivent être définis dans un projet distinct. Le projet contenant le service doit avoir un code de mappage qui permet de cartographier les objets de domaine vers les DTO.
An ASP.NET le projet MVC est de nature similaire - il s'adapte votre service/Otd (ou d'objets de domaine directement) pour une présentation de la technologie, HTML en particulier. En tant que tel, le DTOs ne devrait pas être au courant des modèles de vue. Au lieu de cela, le contrôleur MVC devrait invoquer la mise en correspondance entre les DTO et les Modèles de vue. Cela peut être fait dans un divers moyens mais ce que j'ai trouvé le plus efficace est un constructeur dans le ViewModel acceptant un DTO. En outre, dans les cas où une action de controller justifie la création d'un DTO à renvoyer au service, le ViewModel peut contenir une méthode de création du dto basée sur le ViewModel. Il contient tous les codes de mappage dans le modèle de vue le plus proche des données réelles - une instance de spécialiste de l'information de pattern. Une autre façon de mettre en œuvre ce serait d'utiliser quelque chose comme AutoMapper qui utilise la cartographie basée sur les conventions pour éviter le code boilerplate. En dehors de cela, je considère exagéré, sauf s'il est appelé pour.
dans de nombreux cas, votre modèle de vue finit par ressembler au DTO mais avec ASP.NET attributs spécifiques de MVC pour la liaison et la validation. Même si cela peut sembler comme une violation de sec, ce sont vraiment des responsabilités distinctes.
tout d'abord, utilisez toujours des modèles de vue explicites pour vos vues, ne passez pas les DTO jusqu'à la vue. C'est un peu plus de travail d'avance, mais cela vous donne plus de contrôle sur exactement quelles données est nécessaire dans la vue (il empêche également un cadre comme EF de sideloading beaucoup de données supplémentaires que vous pouvez ou ne pouvez pas utiliser)
dans un Deuxième temps, cet article présente le modèle Orchestrator http://www.simple-talk.com/dotnet/asp.net/never-mind-the-controller,-here-is-the-orchestrator/ ce qui est probablement juste un autre nom pour un autre motif, mais j'aime le format.
Essentiellement, vous créez un Orchestrateur pour chaque Contrôleur. L'orchestrateur prend les données (typiquement un ViewModel, et tous les autres types de données de base nécessaires, en particulier ceux du HttpContext), et renvoie un ViewModel (si nécessaire pour la vue, sinon un autre retour type.)
ce format vous donne l'avantage de pouvoir facilement tester en unité la logique réelle sans avoir à essayer de vous moquer du truc HttpContext dont les contrôleurs ont besoin.
ressemble à quelque chose que vous voulez faire dans une classe/module de cartographie spécialement conçu.
je donnerais personnellement à mon controller une dépendance sur un service de mappage et puis délègue la conversion réelle à celle-ci avant de retourner la vue avec un nouveau modèle de vue mappé.
public class DemoController : Controller
{
private readonly IMappingService _mappingService;
public DemoController(IMappingService mappingService)
{
_mappingService = mappingService;
}
public ActionResult Stuff()
{
var vm = _mappingService.Map(yourDto);
return View(vm);
}
}
une bonne approche est de surcharger le constructeur sur votre ViewModel avec un second constructeur qui a le dto comme paramètre. Cela signifie que vous pouvez gérer la cartographie dans le Modèle de Vue lui-même. Cela permet à votre contrôleur de rester en ordre sans avoir à configurer un service de cartographie.