À partir de cette question , il semble logique qu'un contrôleur crée un ViewModel qui reflète plus précisément le modèle que la vue essaie d'afficher, mais je suis curieux de connaître certaines des conventions (je suis nouveau dans le modèle MVC , si ce n'était pas déjà évident).
Fondamentalement, j'avais les questions suivantes:
- J'aime normalement avoir une classe / fichier. Cela a-t-il un sens avec un ViewModel s'il est uniquement créé pour transférer des données d'un contrôleur vers une vue?
- Si un ViewModel appartient à son propre fichier et que vous utilisez une structure de répertoire / projet pour garder les choses séparées, à quoi appartient le fichier ViewModel ? Dans le répertoire des contrôleurs ?
C'est essentiellement ça pour l'instant. J'ai peut-être quelques questions à venir, mais cela me dérange depuis une heure environ, et je peux trouver des conseils cohérents ailleurs.
EDIT: En regardant l'exemple d' application NerdDinner sur CodePlex, il semble que les ViewModels fassent partie des contrôleurs , mais cela me met encore mal à l'aise de ne pas être dans leurs propres fichiers.
asp.net-mvc
asp.net-mvc-viewmodel
jerhinesmith
la source
la source
Réponses:
Je crée ce que j'appelle un "ViewModel" pour chaque vue. Je les place dans un dossier appelé ViewModels dans mon projet Web MVC. Je les nomme d'après le contrôleur et l'action (ou la vue) qu'ils représentent. Donc, si je dois transmettre des données à la vue SignUp sur le contrôleur d'appartenance, je crée une classe MembershipSignUpViewModel.cs et la place dans le dossier ViewModels.
J'ajoute ensuite les propriétés et méthodes nécessaires pour faciliter le transfert des données du contrôleur vers la vue. J'utilise Automapper pour passer de mon ViewModel au modèle de domaine et revenir si nécessaire.
Cela fonctionne également bien pour les ViewModels composites qui contiennent des propriétés qui sont du type d'autres ViewModels. Par exemple, si vous avez 5 widgets sur la page d'index dans le contrôleur d'appartenance et que vous avez créé un ViewModel pour chaque vue partielle - comment passez-vous les données de l'action Index aux partiels? Vous ajoutez une propriété à MembershipIndexViewModel de type MyPartialViewModel et lors du rendu du partiel, vous passeriez dans Model.MyPartialViewModel.
Le faire de cette façon vous permet d'ajuster les propriétés partielles de ViewModel sans avoir à changer du tout la vue Index. Il passe toujours dans Model.MyPartialViewModel, il y a donc moins de chance que vous deviez parcourir toute la chaîne des partiels pour corriger quelque chose lorsque tout ce que vous faites est d'ajouter une propriété au ViewModel partiel.
J'ajouterai également l'espace de noms "MyProject.Web.ViewModels" au web.config afin de me permettre de les référencer dans n'importe quelle vue sans jamais ajouter une déclaration d'importation explicite sur chaque vue. Le rend juste un peu plus propre.
la source
Séparer les classes par catégorie (contrôleurs, modèles d'affichage, filtres, etc.) est un non-sens.
Si vous souhaitez écrire du code pour la section Accueil de votre site Web (/), créez un dossier nommé Home et placez-y le HomeController, IndexViewModel, AboutViewModel, etc. et toutes les classes connexes utilisées par les actions Home.
Si vous avez partagé des classes, comme un ApplicationController, vous pouvez le mettre à la racine de votre projet.
Pourquoi séparer les choses qui sont liées (HomeController, IndexViewModel) et garder les choses ensemble qui n'ont aucune relation (HomeController, AccountController)?
J'ai écrit un article de blog sur ce sujet.
la source
Je garde mes classes d'application dans un sous-dossier appelé "Core" (ou une bibliothèque de classes séparée) et j'utilise les mêmes méthodes que l' exemple d'application KIGG mais avec quelques légères modifications pour rendre mes applications plus SÈCHES.
Je crée une classe BaseViewData dans / Core / ViewData / où je stocke les propriétés communes à l'ensemble du site.
Après cela, je crée également toutes mes classes ViewData dans le même dossier qui dérivent ensuite de BaseViewData et ont des propriétés spécifiques à la vue.
Ensuite, je crée un ApplicationController dont tous mes contrôleurs dérivent. ApplicationController possède une méthode GetViewData générique comme suit:
Enfin, dans mon action de contrôleur, je fais ce qui suit pour construire mon modèle ViewData
Je pense que cela fonctionne vraiment bien et qu'il garde vos vues bien rangées et vos contrôleurs maigres.
la source
Une classe ViewModel est là pour encapsuler plusieurs éléments de données représentés par des instances de classes en un seul objet facile à gérer que vous pouvez transmettre à votre vue.
Il serait logique d'avoir vos classes ViewModel dans leurs propres fichiers, dans leur propre répertoire. Dans mes projets, j'ai un sous-dossier du dossier Modèles appelé ViewModels. C'est là que mes ViewModels (par exemple
ProductViewModel.cs
) vivent.la source
Il n'y a pas de bon endroit pour conserver vos modèles. Vous pouvez les conserver dans un assemblage séparé si le projet est grand et qu'il y a beaucoup de ViewModels (Data Transfer Objects). Vous pouvez également les conserver dans un dossier séparé du projet de site. Par exemple, dans Oxite, ils sont placés dans le projet Oxite qui contient également de nombreuses classes différentes. Les contrôleurs d'Oxite sont déplacés vers un projet séparé et les vues sont également dans un projet distinct.
Dans CodeCampServer, les ViewModels sont nommés * Form et sont placés dans le projet UI dans le dossier Models.
Dans le projet MvcPress , ils sont placés dans le projet Data, qui contient également tout le code pour travailler avec la base de données et un peu plus (mais je n'ai pas recommandé cette approche, c'est juste pour un échantillon)
Vous pouvez donc voir qu'il existe de nombreux points de vue. Je garde généralement mes ViewModels (objets DTO) dans le projet de site. Mais lorsque j'ai plus de 10 modèles, je préfère les déplacer vers un assemblage séparé. Habituellement, dans ce cas, je déplace également les contrôleurs vers un assemblage séparé.
Une autre question est de savoir comment mapper facilement toutes les données du modèle vers votre ViewModel. Je suggère de jeter un œil à la bibliothèque AutoMapper . Je l'aime beaucoup, ça fait tout un sale boulot pour moi.
Et moi aussi je suggère de regarder le projet SharpArchitecture . Il fournit une très bonne architecture pour les projets et il contient beaucoup de cadres et de guides sympas et une grande communauté.
la source
voici un extrait de code de mes meilleures pratiques:
la source
Nous jetons tous nos ViewModels dans le dossier Modèles (toute notre logique métier est dans un projet ServiceLayer distinct)
la source
Personnellement, je suggère que si le ViewModel est tout sauf trivial, utilisez une classe distincte.
Si vous avez plus d'un modèle de vue, je suggère qu'il soit judicieux de le partitionner dans au moins un répertoire. si le modèle de vue est ultérieurement partagé, l'espace de nom impliqué dans le répertoire facilite le déplacement vers un nouvel assembly.
la source
Dans notre cas, nous avons les modèles avec les contrôleurs dans un projet distinct des vues.
En règle générale, nous avons essayé de déplacer et d'éviter la plupart des éléments ViewData ["..."] vers le ViewModel afin d'éviter les castings et les chaînes magiques, ce qui est une bonne chose.
Le ViewModel contient également certaines propriétés communes telles que les informations de pagination pour les listes ou les informations d'en-tête de la page pour dessiner les fils d'Ariane et les titres. En ce moment, la classe de base contient trop d'informations à mon avis et nous pouvons la diviser en trois parties, les informations les plus élémentaires et nécessaires pour 99% des pages sur un modèle de vue de base, puis un modèle pour les listes et un modèle pour les formulaires qui contiennent des données spécifiques pour ces scénarios et héritent de celui de base.
Enfin, nous implémentons un modèle de vue pour chaque entité afin de traiter les informations spécifiques.
la source
code dans le contrôleur:
code dans le modèle de vue:
projets:
DevJet.Web (le projet Web ASP.NET MVC)
DevJet.Web.App.Dictionary (un projet de bibliothèque de classes distinct)
dans ce projet, j'ai fait des dossiers comme: DAL, BLL, BO, VM (dossier pour voir les modèles)
la source
Créez une classe de base de modèle de vue qui possède des propriétés généralement requises comme le résultat de l'opération et des données contextuelles, vous pouvez également mettre les données et les rôles utilisateur actuels
Dans la classe de contrôleur de base, une méthode telle que PopulateViewModelBase () cette méthode remplira les données contextuelles et les rôles d'utilisateur. HasError et ErrorMessage, définissez ces propriétés s'il y a exception lors de l'extraction des données de service / db. Liez ces propriétés en vue pour afficher l'erreur. Les rôles utilisateur peuvent être utilisés pour afficher la section de masquage sur la vue en fonction des rôles.
Pour remplir les modèles de vue dans différentes actions get, il peut être rendu cohérent en ayant un contrôleur de base avec la méthode abstraite FillModel
Dans les contrôleurs
la source