web-dev-qa-db-fra.com

MVC ViewBag Best Practice

Pour le ViewBag, j'ai entendu dire que c'était un non-non à utiliser. Je suppose que le contenu du ViewBag doit être incorporé dans un modèle de vue?

Question:

  1. Est mon hypothèse au-dessus de la meilleure pratique. (Ne pas utiliser un ViewBag et deuxième pour l'avoir dans le modèle de vue)

  2. Y a-t-il des situations où un ViewBag est absolument nécessaire?

32
Nate Pet

ViewBag est un dictionnaire dynamique. Ainsi, lorsque vous utilisez ViewBag pour transférer des données entre des méthodes d'action et des vues, votre compilateur ne pourra pas intercepter si vous faites une faute de frappe dans votre code lorsque vous essayez d'accéder à l'élément ViewBag dans votre vue. Votre vue se bloque lors de l'exécution :(

En règle générale, il est judicieux d'utiliser un modèle de vue pour transférer des données entre vos méthodes d'action et vos vues. Le modèle de vue est une classe POCO simple qui possède des propriétés spécifiques à la vue. Donc, si vous souhaitez transmettre des données supplémentaires à afficher, ajoutez une nouvelle propriété à votre modèle de vue et utilisez-la. Les vues fortement typées rendent le code plus propre et plus facile à gérer. Avec cette approche, vous n'avez pas besoin de faire un cast explicite de votre élément de dictionnaire viewbag vers certains types d'avant en arrière que vous devez faire avec view bag.

public class ProductsForCategoryVm
{
  public string CategoryName { set;get; }
  public List<ProductVm> Products { set;get;}    
}
public class ProductVm
{
  public int Id {set;get;} 
  public string Name { set;get;}
}

Et dans votre méthode d'action, créez un objet de ce modèle de vue, chargez les propriétés et envoyez-le à la vue.

public ActionResult Category(int id)
{
  var vm= new ProductsForCategoryVm();
  vm.CategoryName = "Books";
  vm.Products= new List<ProductVm> {
     new ProductVm { Id=1, Name="The Pragmatic Programmer" },
     new ProductVm { Id=2, Name="Clean Code" }
  }
  return View(vm);
}

Et votre vue, qui est fortement typée dans le modèle de vue,

@model ProductsForCategoryVm
<h2>@Model.CategoryName</h2>
@foreach(var item in Model.Products)
{
    <p>@item.Name</p>
}

Données déroulantes?

De nombreux tutoriels/livres contiennent des exemples de code qui utilisent ViewBag pour les données déroulantes. Personnellement, je pense toujours que ViewBag ne devrait pas être utilisé pour cela. Il doit s'agir d'une propriété de type List<SelectListItem> dans votre modèle de vue pour transmettre les données déroulantes. Voici un post avec un exemple de code sur la façon de le faire.

Y a-t-il des situations où un ViewBag est absolument nécessaire?

Il existe des cas d'utilisation valides où vous pouvez ( pas nécessaire ) utiliser ViewBag pour envoyer des données. Par exemple, vous souhaitez afficher quelque chose sur votre page de mise en page, vous pouvez utiliser ViewBag pour cela. Un autre exemple est ViewBag.Title (pour le titre de la page ) présent dans le modèle MVC par défaut.

public ActionResult Create()
{
   ViewBag.AnnouncementForEditors="Be careful";
   return View();
}

Et dans la mise en page, vous pouvez lire le ViewBag.AnnouncementForEditors

<body>
<h1>@ViewBag.AnnouncementForEditors</h1>
<div class="container body-content">
    @RenderBody()
</div>
</body>
29
Shyju

1) Mon hypothèse est-elle au-dessus de la meilleure pratique. (Ne pas utiliser un ViewBag et deuxième pour l'avoir dans le modèle de vue)

Vous devez utiliser autant que possible les viewmodels au lieu de transmettre des données via ViewBag.

2) Y a-t-il des situations où un ViewBag est absolument nécessaire?

Il n'y a aucune situation où un ViewBag est absolument nécessaire. Cependant, il y a certaines données que je préfère personnellement utiliser ViewBag au lieu de View Model. Par exemple, lorsque j'ai besoin de remplir une liste déroulante pour des valeurs prédéfinies (c.-à-d. Les villes), j'utilise ViewBag pour transporter le tableau SelectListItem à afficher. Je préfère ne pas polluer mes ViewModels avec ces données.

30
SadullahCeran

1) Mon hypothèse est-elle supérieure à la meilleure pratique. (Ne pas utiliser un ViewBag et deuxième pour l'avoir dans le modèle de vue)

Oui.

2) Y a-t-il des situations où un ViewBag est absolument nécessaire?

Non. Tout ce que vous avez stocké dans un ViewBag peut entrer dans le modèle de vue transmis à la vue.

4
Darin Dimitrov

Le problème avec ViewBags et les meilleures pratiques recommandées se résument à la vérification de l'heure de compilation. Les ViewBags ne sont que des dictionnaires et avec cela vous obtenez des chaînes "magiques", donc si vous finissez par changer le type d'objet de l'un des éléments du viewbag ou le nom de la clé, vous ne le saurez pas avant l'exécution, même si vous précompilez les vues à l'aide de <MvcBuildViews>true</MvcBuildViews>.

Il est préférable de s'en tenir aux modèles de vue, même si vous devez les modifier pour s'adapter à une vue spécifique de temps en temps.

4
Chris S

J'ai trouvé une certaine utilité pour ViewBag où il existe des fonctionnalités communes à toutes les pages, et la fonctionnalité ne dépend pas de la page affichée. Par exemple, supposons que vous construisez StackOverflow. Le tableau des tâches apparaît sur chaque page, mais les tâches affichées n'ont rien à voir avec la page (mon utilisation était similaire dans le concept). L'ajout d'une propriété à chaque ViewModel serait difficile et prend du temps, et un lot de duvet à vos tests. Je ne pense pas que cela en vaille la peine dans cette situation.

J'ai utilisé une classe ViewModel de base avec les données transversales, mais si vous en avez plusieurs (par exemple, des travaux et une liste de sites d'échange de pile), vous devez soit commencer à insérer des données supplémentaires, soit un autre abus d'un ViewModel, plus vous avez besoin d'un générateur ViewModel pour remplir les données de base.

Quant au problème des cordes magiques, il existe de nombreuses solutions. Constantes, méthodes d'extension, etc.

Cela dit, si vous avez quelque chose qui s'affiche sur votre page et qui dépend du contexte de la page, un ViewModel est votre ami.

Erick

2
Erick T
  1. Non. Utilisez ViewModels .
  2. Non. Si vous concevez un ViewModel parfait, vous n'avez jamais besoin d'un ViewBag.
1
Tohid

Si vous ne pouvez pas repenser le ViewModel EXISTANT, utilisez ViewBag.

1
Developer

2.Y a-t-il des situations où un ViewBag est absolument nécessaire?

Dans certains cas, vous devrez partager vos données du contrôleur entre les dispositions, les vues et les vues partielles. Dans ce cas, ViewBag est très utile et je doute qu'il existe un meilleur moyen.

0
Dinh Tran

J'ai pensé donner mon avis à ce sujet, car j'ai beaucoup utilisé le ViewBag.

Les seuls avantages réels que vous obtiendrez en l'utilisant sont pour un petit projet, ou dans les cas où vous avez un nouveau projet et que vous voulez simplement lancer la balle et ne pas avoir à vous soucier de créer des charges de classes de modèle.

Lorsque votre projet est plus mature, vous pouvez rencontrer des problèmes avec un comportement inattendu dû à l'utilisation d'une frappe faible dans toute votre application. La logique peut être déroutante, difficile à tester et difficile à dépanner lorsque les choses tournent mal.

En fait, j'ai choisi de supprimer complètement le ViewBag de mes applications et d'empêcher d'autres développeurs de l'utiliser dans la même base de code en lançant des erreurs de compilation lorsqu'ils essayez de le faire, même dans les vues Razor.

Voici un exemple de projet ASP.NET 5 sur GitHub où je l'ai supprimé: https://github.com/davidomid/Mvc5NoViewBag

Et voici un article de blog où j'explique les motivations pour le supprimer et une explication sur le fonctionnement de la solution: https://www.davidomid.com/hate-the-aspnet-mvc-viewbag-as-much- as-i-do-heres-how-to-remove-it

0
David Omid

S'il n'y avait pas de cas d'utilisation pour cela, il ne serait pas implémenté en premier lieu. Oui, vous pouvez tout faire avec ViewModels, mais que faire si vous n'en avez pas vraiment besoin? Un de ces scénarios consiste à modifier des entités. Vous pouvez passer DTO directement en tant que modèle.

@model CategoryDto
<div class="md-form form-sm">
    <input asp-for="Name" class="form-control">
    <label asp-for="Name">("Category Name")</label>
</div>

Mais que se passe-t-il si vous souhaitez sélectionner la catégorie parent? L'entité DTO ne contient idéalement que ses propres valeurs, donc pour remplir la liste de sélection, vous utilisez ViewBag

<select asp-for="ParentId" asp-items="ViewBag.ParentList">
    <option value="">None</option>
</select>

Pourquoi faire ceci? Eh bien, si vous avez 50 types d'entités chacun avec une sorte de sélection à partir de valeurs différentes, vous avez juste évité de créer 50 ViewModels supplémentaires.

0
Xeevis