10-3 Communication avec la vue via un ViewModel
Une autre approche, plutôt que le ViewBag
, est d'utiliser un objet spécialement conçu pour la vue et contenant tout ce que cette dernière a besoin. Évidemment, si la vue n'a besoin que du modèle directement, on peut lui envoyer, mais si elle a besoin de plus, on crée alors un ViewModel
.
Un ViewModel représente les données qu'on veut afficher et traiter dans la vue. Comme ici on veut afficher des événements et des villes, on peut créer un ViewModel
qui contiendra deux propriétés:
- Une liste d'événements (modèle
Evenement
) - Une liste de villes (modèle
Ville
)
Créer le ViewModel
EvenementsIndexViewModel
-
Créer un dossier
Evenements
sous le dossierModels
du projetWeb.Mvc
. Puisque les modèles ont été déplacés dans un projet séparé, nous utiliserons le dossierModels
du projet Web pour lesViewModels
. -
Créer une classe
EvenementsIndexViewModel
. Sous le dossierSnowfall.Web.Mvc/Models/Evenements
, créez une nouvelle classeEvenementsIndexViewModel
.Snowfall.Web.Mvc/Models/Evenements/EvenementsIndexViewModel.csnamespace Snowfall.Web.Mvc.Models.Evenements;
public class EvenementsIndexViewModel
{
}
Propriétés du ViewModel
Pour contenir les données que la vue aura besoin, des propriétés associées doivent exister dans le ViewModel
.
La vue Index
a besoin de 2 propriétés:
- Une liste d'objets de type
Evenement
- Une liste d'objets de type
Ville
Ajoutez ces deux listes à la classe EvenementsIndexViewModel
:
using Snowfall.Domain.Models;
namespace Snowfall.Web.Mvc.Models.Evenements;
public class EvenementsIndexViewModel
{
public required List<Evenement> Evenements { get; set; }
public required List<Ville> Villes { get; set; }
}
Retourner un ViewModel
à la vue
-
Créez une liste de villes en mémoire dans l'action
Index
du contrôleurEvenementsController
, que nous pourrons retourner à la vue. Nous aurons la chance de remplacer cette liste par une liste en provenance de la base de données bientôt.public async Task<IActionResult> Index()
{
List<Evenement> evenements = await _evenementService.GetAll();
List<Ville> villes = new List<Ville>
{
new Ville
{
Id = 1,
Nom = "Montreal",
PaysIso = "CA"
},
new Ville
{
Id = 2,
Nom = "Los Angeles",
PaysIso = "US"
}
};
return View(evenements);
} -
Juste avant le retour de l'action
Index()
, créez une instance deEvenementsIndexViewModel
contenant la liste de villes et d'événements, puis retournez ce nouveau modèle à la vue!:Snowfall.Web.Mvc/Controllers/EvenementsController.cspublic async Task<IActionResult> Index()
{
List<Evenement> evenements = await _evenementService.GetAll();
List<Ville> villes = new List<Ville>
{
new Ville
{
Id = 1,
Nom = "Montreal",
PaysIso = "CA"
},
new Ville
{
Id = 2,
Nom = "Los Angeles",
PaysIso = "US"
}
};
var viewModel = new EvenementsIndexViewModel
{
Villes = villes,
Evenements = evenements
};
return View(viewModel);
}infoÀ noter que le bloc suivant:
Snowfall.Web.Mvc/Controllers/EvenementsController.csvar viewModel = new EvenementsIndexViewModel
{
Villes = villes,
Evenements = evenements
};Est équivalent à:
Snowfall.Web.Mvc/Controllers/EvenementsController.csvar viewModel = new EvenementsIndexViewModel();
viewModel.Villes = villes;
viewModel.Evenements = evenements;On évite cependant de la répétition dans la première version et cette dernière est plus élégante. Ceci dit, il n'y a aucune différence au niveau de la fonctionnalité.