28 votes

Comment remplissez-vous/validez-vous vos ViewModels ?

Je suis curieux de connaître les différentes façons dont les gens construisent leurs ViewModels et les raisons pour lesquelles ils choisissent cette méthode.

Je peux penser à plusieurs façons de le faire :

-1. Référentiel injecté - le contrôleur charge le modèle et mappe vers le ViewModel. Ici, le constructeur du ViewModel pourrait prendre diverses collections pour les définir entre elles, par exemple dans une liste de sélection telle que :

public CustomerController(ISomeRepository repository)
{
   _repository = repository;
}

public ActionResult Create()
{
  CustomerCreateViewModel model = new CustomerCreateViewModel(_repository.GetShipTypes, 
                                                                _repository.GetStates);
..
..
}

-2. ViewModelBuilder - Injecté ou instancié dans le contrôleur avec une instance du référentiel injecté. Appelé via quelque chose comme

\>`var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);`

ou,

var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);

-3. Directement dans le contrôleur (pas de code requis - c'est compliqué)

-4. Un autre service (injecté ou non) qui renvoie un modèle de domaine que le contrôleur mappe ensuite ou un ViewModel (quelqu'un fait cela pour renvoyer un modèle de vue qui n'est pas spécifiquement nommé/noté comme une classe de construction de ViewModel ?)

public JobCreateViewModel BuildJobCreateViewModel(int parentId)
{
   JobCreateViewModel model = new JobCreateViewModel();
   model.JobStatus = _unitOfWork.JobRepository.GetJobStatuses();
   model.States=_unitOfWork.StateRepository.GetAll();
   return model;
}

Maintenant, au retour, en ce qui concerne la validation de vos modèles de vue, héritez-vous d'une classe ViewModel de base pour les validations standard, ou copiez-vous vos validations (ex. attributs d'annotation de données) entre tous vos ViewModels, ou comptez-vous simplement sur la validation côté serveur pour que tout puisse être validé par votre objet de domaine ?

D'autres ? Quelque chose de mieux ? Pourquoi ?

EDITAR Sur la base d'un lien ci-dessous, j'ai trouvé un bel article de Jimmy Bogard sur l'architecture des ViewModels. Bien qu'il ne réponde pas directement à la question ci-dessus, c'est une excellente référence pour quiconque vient ici pour des informations sur les ViewModels. http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

13voto

Darin Dimitrov Points 528142

J'injecte un service dans le contrôleur, pas un référentiel, puis j'utilise AutoMapper pour le convertir en un modèle de vue. L'avantage de la couche de service dans ce cas est qu'elle pourrait regrouper plusieurs opérations simples provenant d'un ou plusieurs référentiels en une seule opération exposant un modèle de domaine. Exemple :

private readonly ICustomerService _service;
public CustomerController(ICustomerService service)
{
    _service = service;
}

[AutoMap(typeof(Customer), typeof(CustomerViewModel))]
public ActionResult Create(int id)
{
    Customer customer = _service.GetCustomer(id);
    return View(customer);
}

Dans cet exemple, AutoMap est un filtre d'action personnalisé que je peux écrire et qui s'exécute après l'action du contrôleur, inspecte l'objet renvoyé et utilise les mappages AutoMapper définis pour le faire correspondre au type de destination spécifié. Ainsi, la vue obtient le CustomerViewModel correspondant comme type de modèle. Cela aurait été équivalent à :

public ActionResult Create(int id)
{
    Customer customer = _service.GetCustomer(id);
    CustomerViewModel vm = Mapper.Map<Customer, CustomerViewModel>(customer);
    return View(vm);
}

c'est juste que c'est trop de plomberie et de code répétitif qui pourrait être centralisé.

Je vous recommande également de regarder le vidéo sur la mise au régime de vos contrôleurs de Jimmy Bogard.

0voto

Dean Points 923

Notre méthode consiste à injecter le référentiel dans le contrôleur et à le faire correspondre au ViewModel en utilisant Automapper. http://automapper.org/ . Nos ViewModels contiennent des attributs d'annotation de données pour permettre à la validation de se produire sur le client.

Nous appelons des méthodes sur le référentiel qui renvoient des objets du domaine (Entity Framework). Les objets du domaine sont mis en correspondance avec le ViewModel. Nous avons tendance à utiliser le même ViewModel pour les modifications et les ajouts, de sorte que les annotations de données ne sont nécessaires qu'une seule fois. Dans sa forme la plus simple, cela ressemble au code suivant :

    public ActionResult List(int custId, int projId)
    {
        var users = _userRepository.GetByCustomerId(custId);
        var userList = Mapper.Map<IEnumerable<CMUser>, IEnumerable<UserListViewModel>>(users);
        return View(userList);
    }

0voto

Jason Points 8799

Je viens de terminer un projet où nous avons fait une variation sur le #4. Nous avions une classe de service injectée dans le contrôleur. La classe de service avait des dépendances sur le référentiel et sur une classe de construction de modèle (nous l'avons appelée model factory).

Le contrôleur fait appel à la classe de service, qui gère la logique de validation de l'activité, puis va chercher les modèles de vue dans la fabrique appropriée. Les modèles eux-mêmes s'appuient sur les annotations de données pour la validation des entrées.

Cela a très bien fonctionné pour notre équipe. La séparation des préoccupations était suffisante pour permettre aux développeurs de faire leur travail sans se gêner les uns les autres, mais elle était suffisamment gérable pour comprendre ce qui se passait.

C'est la première fois que nous l'essayons et nous allons nous y tenir. Je suis curieux de voir comment les autres réagissent.

0voto

Mike Brown Points 5874

J'utilise une couche de service qui cache le modèle de domaine au contrôleur qui renvoie les ViewModels à partir des méthodes de service. Cela me permet d'apporter des modifications au modèle de domaine sans que cela ait un impact sur le client.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X