web-dev-qa-db-fra.com

ASP.NET MVC - Comment utiliser exactement les modèles de vue

Disons que j'ai une page qui permet de modifier les détails d'un utilisateur, j'ai donc un ViewModel comme celui-ci:

public class UserViewModel {
    public string Username { get; set; }
    public string Password { get; set; }
    public int ManagerId { get; set; }
    public string Category { get; set; }
}

Donc, sur mon action EditUser, je peux le faire renvoyer par le classeur de modèle, puis je peux le mapper au modèle de domaine:

public ActionResult EditUser(UserViewModel user) {
    ...

Cependant, la page qui affiche le formulaire a également besoin de détails tels qu'une liste de gestionnaires et de catégories pour fournir des listes déroulantes pour ces champs. Il peut également afficher une liste d'autres utilisateurs dans une barre latérale afin que vous puissiez basculer entre les différents utilisateurs que vous modifiez.

Alors j'ai un autre modèle de vue:

public class ViewUserViewModel {
    public UserViewModel EditingUser { get; set; }
    public IEnumerable<SelectListItem> Managers { get; set; }
    public IEnumerable<SelectListItem> Categories { get; set; }
    public IEnumerable<SelectListItem> AllUsers { get; set; }
}

Est-ce la bonne façon de procéder? Sont-ils tous les deux des modèles de vue? Dans l'affirmative, existe-t-il une convention de dénomination que je devrais utiliser pour pouvoir distinguer les machines virtuelles qui sont comme des modèles et les machines virtuelles qui contiennent uniquement des données pour la page?

Ai-je tout faux?

36
littlecharva

Comment je fais cela en raccourci:

  1. Créez une classe ViewModel distincte pour chaque formulaire de la page, puis je rend ces classes avec PartialViews sous la forme @{Html.RenderPartial("PartialName", Model.PartialModel);}.
  2. Si la page contient des choses comme les métas html, je crée une classe séparée pour les métas et la mets en section sur la page.
  3. Les cas de repos comme "devrais-je mettre cela en classe séparée?" est votre jugement.

Ainsi, par exemple, vous avez une page qui a une sorte de barre de connexion/d'enregistrement ou une fenêtre contextuelle.

public class SomePageViewModel
{
    public RegisterBarVM Register { get; set; }
    public LoginBarVM LoginBar { get; set; }

    public MetasVM Metas { get; set; }
    public string MaybePageTitle { get; set;}
    public string MaybePageContent { get; set;}

    [HiddenInput(DisplayValue = false)]
    public int IdIfNeeded { get; set; }

    public IEnumerable<SelectListItem> SomeItems {get; set;}
    public string PickedItemId { get;set; }
}

public class RegisterBarVM
{
    public string RegisterUsername {get;set;}
    public string RegisterPassword {get;set;}
    //...
}

public class LoginBarVM
{
    public string LoginUserame {get;set;}
    public string LoginPassword {get;set;}
    //...
}

//cshtml
@model yourClassesNamespace.SomePageViewModel
@{
    Html.RenderPartial("LoginBar", Model.LoginBar); //form inside
    Html.RenderPartial("RegisterBar", Model.RegisterBar); //form inside

    using(Html.BeginForm())
    {
        @Html.EditorFor(m => m.IdIfNeeded)
        @Hmtl.EditorFor(m => m.MaybePageTitle)
        @Hmtl.EditorFor(m => m.MaybePageContent)

        @Hmtl.DropDownListFor(m => m.PickedItemId, new SelectList(Model.SomeItems))

        <input type="submit" value="Update" />
    }
}

@section Metas {
    @{Html.RenderPartial("Meatas", Model.Metas}
}

A propos des modèles d'éditeur Brad Wilsons Blog et juste google ou recherchez des ressources de piles sur les modèles d'affichage/éditeur et HtmlHelpers. Ils sont tous très utiles pour créer des sites Web cohérents.

20
Mariusz

"Afficher le modèle" n'est qu'un modèle. Le nom n'a rien de magique, mais en général, toute classe transmise à une vue (que ce soit pour afficher simplement des données ou à des fins de soumission de formulaire) est appelée "modèle de vue" et porte un nom comme FooViewModel ou FooVM pour indiquer qu'il fait partie de ce modèle "Afficher le modèle".

Je ne veux pas être trop philosophique sur vous, mais je pense qu'un peu de référence sur les motifs en jeu sera utile. ASP.NET MVC encourage évidemment un modèle architectural MVC (Model-View-Controller). Dans MVC, le modèle est le conteneur de toutes les applications logique métier. Le contrôleur est responsable du traitement de la demande, de la récupération du modèle, du rendu de la vue avec ce modèle et du renvoi d'une réponse. Cela semble être beaucoup de responsabilité, mais en réalité, le cadre gère la plupart de cela en arrière-plan, donc les contrôleurs sont généralement (et devraient être) très légers sur le code. Ils sont responsables de la quantité minimale de fonctionnalités pour tout câbler. Enfin, la vue est chargée de créer la couche d'interface utilisateur qui permet à l'utilisateur d'interagir avec les données du modèle. Il est pas responsable des données elles-mêmes, et ne devrait pas l'être (ViewData/ViewBag est une assez grosse violation ici, au moins autant que la façon dont il finit par être utilisé par les développeurs dans la pratique).

Cela signifie donc que la majeure partie de votre logique d'application doit se trouver dans votre modèle, et c'est généralement une bonne chose. Cependant, étant donné que le modèle est le paradis des données d'application, il est généralement conservé dans une base de données ou similaire. Cela crée un certain conflit d'intérêts, car vous devez maintenant lancer un équilibre entre les données qui doivent être conservées et celles qui ne doivent exister qu'à des fins d'affichage.

C'est là que les modèles de vue entrent en jeu. MVVM (Model-View-View Model), un modèle quelque peu parallèle à MVC, reconnaît les problèmes inhérents à une approche d'un modèle à la règle pour tous. Je n'entrerai pas dans les détails ici, car MVC n'utilise pas ce modèle. Cependant, la plupart des développeurs ASP.NET MVC ont coopté le modèle d'affichage de MVVM. Vous vous retrouvez essentiellement avec une base de données entité (le modèle traditionnel), puis généralement de nombreux modèles de vue différents qui représentent cette entité dans différents états. Cela permet à votre modèle de contenir la logique métier pertinente pour la persistance tandis que le ou les modèles de vue contiennent la logique métier pertinente pour afficher, créer et mettre à jour ce modèle.

Je me suis un peu éloigné de la piste, mais en un mot, ce que vous faites est parfaitement acceptable. En fait, c'est une bonne pratique. Créez autant de modèles de vue que votre application l'exige et utilisez-les pour stocker réellement les données et la logique métier nécessaires à vos vues. (Cela inclut des choses comme SelectLists. Ni votre contrôleur ni votre vue ne devraient avoir besoin de savoir comment créer un SelectList pour une liste déroulante.)

94
Chris Pratt

Personnellement, je préfère mettre toutes les informations nécessaires pour que la page s'affiche dans le ViewModel, car c'est le but du ViewModel - fournir toutes les données pour la View. Ainsi, mon UserViewModel contiendrait des propriétés pour Managers, Categories et AllUsers et le contrôleur remplirait ces collections avant de passer le ViewModel à la vue.

C'est essentiellement ce que vous avez fait - cela supprime simplement le ViewModel supplémentaire de l'équation.

J'ai également vu d'autres programmeurs utiliser le ViewData pour envoyer les listes déroulantes à la vue, mais je n'aime pas cela parce que ViewData n'est pas fortement typé, alors qu'un ViewModel l'est.

9
Jason Berkan