Partie 3 : Vues et modèles de vue
par Jon Galloway
Le Magasin de musique MVC est une application de tutoriel qui présente et explique pas à pas comment utiliser ASP.NET MVC et Visual Studio pour le développement web.
Le Magasin de musique MVC est un exemple d’implémentation de magasin léger qui vend des albums de musique en ligne et implémente l’administration de site de base, la connexion utilisateur et les fonctionnalités de panier d’achat.
Cette série de tutoriels détaille toutes les étapes effectuées pour générer l’exemple d’application ASP.NET magasin de musique MVC. La partie 3 traite des vues et des viewModels.
Jusqu’à présent, nous avons simplement retourné des chaînes à partir d’actions du contrôleur. C’est un bon moyen de se faire une idée du fonctionnement des contrôleurs, mais ce n’est pas la façon dont vous souhaitez créer une application web réelle. Nous allons souhaiter une meilleure façon de générer du code HTML pour les navigateurs visitant notre site, un moyen où nous pouvons utiliser des fichiers modèles pour personnaliser plus facilement le contenu HTML renvoyé. C’est exactement ce que fait Views.
Ajout d’un modèle View
Pour utiliser un modèle d’affichage, nous allons modifier la méthode HomeController Index pour renvoyer un ActionResult et lui faire renvoyer View(), comme ci-dessous :
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
La modification ci-dessus indique qu’au lieu de renvoyer une chaîne, nous voulons plutôt utiliser un « View » pour générer un résultat.
Nous allons maintenant ajouter un modèle d’affichage approprié à notre projet. Pour ce faire, nous allons positionner le curseur de texte dans la méthode d’action Index, puis cliquer avec le bouton droit et sélectionner « Ajouter une vue ». La boîte de dialogue Ajouter une vue s’affiche :
La boîte de dialogue « Ajouter une vue » nous permet de générer rapidement et facilement des fichiers de modèle d’affichage. Par défaut, la boîte de dialogue « Ajouter une vue » préremplira le nom du modèle d’affichage à créer afin qu’il corresponde à la méthode d’action qui l’utilisera. Étant donné que nous avons utilisé le menu contextuel « Ajouter une vue » dans la méthode d’action Index() de notre HomeController, la boîte de dialogue « Ajouter une vue » ci-dessus contient « Index » comme nom d’affichage prérempli par défaut. Nous n’avons pas besoin de modifier les options de cette boîte de dialogue. Cliquez donc sur le bouton Ajouter.
Lorsque nous cliquez sur le bouton Ajouter, Visual Web Developer crée un modèle d’affichage Index.cshtml pour nous dans le répertoire \Views\Accueil, en créant le dossier s’il n’existe pas déjà.
Le nom et l’emplacement du dossier du fichier « Index.cshtml » sont importants et suivent les conventions de nommage MVC par défaut ASP.NET. Le nom du répertoire, \Views\Home, correspond au contrôleur, qui est nommé HomeController. Le nom du modèle de vue, Index, correspond à la méthode d’action du contrôleur qui affichera la vue.
ASP.NET MVC nous permet d’éviter d’avoir à spécifier explicitement le nom ou l’emplacement d’un modèle d’affichage lorsque nous utilisons cette convention de nommage pour retourner une vue. Par défaut, il affiche le modèle de vue \Views\Home\Index.cshtml lorsque nous écrivons du code comme ci-dessous dans notre HomeController :
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
Visual Web Developer a créé et ouvert le modèle de vue « Index.cshtml » après avoir cliqué sur le bouton « Ajouter » dans la boîte de dialogue « Ajouter une vue ». Le contenu d’Index.cshtml est illustré ci-dessous.
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
Cette vue utilise la syntaxe Razor, qui est plus concise que le moteur d’affichage Web Forms utilisé dans ASP.NET Web Forms et les versions précédentes de ASP.NET MVC. Le moteur de vue Web Forms est toujours disponible dans ASP.NET MVC 3, mais de nombreux développeurs trouvent que le moteur de vue Razor s’adapte très bien ASP.NET développement MVC.
Les trois premières lignes définissent le titre de la page à l’aide de ViewBag.Title. Nous verrons bientôt comment cela fonctionne plus en détail, mais nous allons d’abord mettre à jour le texte du titre de texte et afficher la page. Mettez à jour la <balise h2> pour indiquer « Il s’agit de la page d’accueil » comme indiqué ci-dessous.
@{
ViewBag.Title = "Index";
}
<h2>This is the Home Page</h2>
L’exécution de l’application montre que notre nouveau texte est visible sur la page d’accueil.
Utilisation d’une disposition pour les éléments de site courants
La plupart des sites web ont du contenu partagé entre de nombreuses pages : navigation, pieds de page, images de logo, références de feuille de style, etc. Le moteur d’affichage Razor facilite la gestion à l’aide d’une page appelée _Layout.cshtml qui a été automatiquement créée pour nous dans le dossier /Views/Shared.
Double-cliquez sur ce dossier pour afficher le contenu ci-dessous.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")"
type="text/javascript"></script>
</head>
<body>
@RenderBody()
</body>
</html>
Le contenu de nos vues individuelles sera affiché par la @RenderBody() commande, et tout contenu courant que nous voulons afficher en dehors de celui-ci peut être ajouté au balisage _Layout.cshtml. Nous voulons que notre Magasin de musique MVC ait un en-tête commun avec des liens vers notre page d’accueil et notre zone Store sur toutes les pages du site. Nous allons donc l’ajouter au modèle directement au-dessus de cette @RenderBody() instruction.
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")"
rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")"
type="text/javascript"></script>
</head>
<body>
<div id="header">
<h1>
ASP.NET MVC MUSIC STORE</h1>
<ul id="navlist">
<li class="first"><a href="/"
id="current">Home</a></li>
<li><a
href="/Store/">Store</a></li>
</ul>
</div>
@RenderBody()
</body>
</html>
Mise à jour de la feuille de style
Le modèle de projet vide comprend un fichier CSS très simplifié qui inclut uniquement les styles utilisés pour afficher les messages de validation. Notre concepteur a fourni des CSS et des images supplémentaires pour définir l’apparence de notre site. Nous allons donc les ajouter maintenant.
Le fichier CSS mis à jour et les images sont inclus dans le répertoire contenu de MvcMusicStore-Assets.zip qui est disponible sur MVC-Music-Store. Nous allons les sélectionner dans Windows Explorer et les déposer dans le dossier Contenu de notre solution dans Visual Web Developer, comme indiqué ci-dessous :
Vous serez invité à confirmer si vous souhaitez remplacer le fichier Site.css existant. Cliquez sur Oui.
Le dossier Content de votre application s’affiche désormais comme suit :
Nous allons maintenant exécuter l’application et voir à quoi ressemblent nos modifications sur la page d’accueil.
- Examinons ce qui a changé : la méthode d’action Index de HomeController a trouvé et affiché le modèle \Views\Home\Index.cshtmlView, même si notre code appelé « return View() », car notre modèle View a suivi la convention de nommage standard.
- La page d’accueil affiche un message d’accueil simple qui est défini dans le modèle de vue \Views\Home\Index.cshtml.
- La page d’accueil utilise notre modèle _Layout.cshtml. Par conséquent, le message d’accueil est contenu dans la disposition HTML de site standard.
Utilisation d’un modèle pour transmettre des informations à notre affichage
Un modèle d’affichage qui affiche simplement du code HTML codé en dur ne fera pas un site web très intéressant. Pour créer un site web dynamique, nous voulons plutôt transmettre des informations de nos actions de contrôleur à nos modèles d’affichage.
Dans le modèle Model-View-Controller, le terme Model fait référence aux objets qui représentent les données de l’application. Souvent, les objets de modèle correspondent à des tables de votre base de données, mais ils n’ont pas besoin de le faire.
Les méthodes d’action du contrôleur qui retournent un Objet ActionResult peuvent passer un objet de modèle à la vue. Cela permet à un contrôleur d’empaqueter proprement toutes les informations nécessaires pour générer une réponse, puis de transmettre ces informations à un modèle d’affichage à utiliser pour générer la réponse HTML appropriée. C’est plus facile à comprendre en le voyant en action. Nous allons donc commencer.
Tout d’abord, nous allons créer des classes de modèle pour représenter les genres et les albums au sein de notre magasin. Commençons par créer une classe Genre. Cliquez avec le bouton droit sur le dossier « Modèles » dans votre projet, choisissez l’option « Ajouter une classe » et nommez le fichier « Genre.cs ».
Ajoutez ensuite une propriété Name de chaîne publique à la classe qui a été créée :
public class Genre
{
public string Name { get; set; }
}
Remarque : si vous vous demandez, la notation { get; set; } utilise la fonctionnalité de propriétés implémentées automatiquement de C#. Cela nous donne les avantages d’une propriété sans nous obliger à déclarer un champ de stockage.
Ensuite, suivez les mêmes étapes pour créer une classe Album (nommée Album.cs) qui a une propriété Title et Genre :
public class Album
{
public string Title { get; set; }
public Genre Genre { get; set; }
}
Maintenant, nous pouvons modifier storeController pour utiliser des vues qui affichent des informations dynamiques à partir de notre modèle. Si, à des fins de démonstration, nous avons nommé nos albums en fonction de l’ID de demande, nous pouvons afficher ces informations comme dans la vue ci-dessous.
Nous allons commencer par modifier l’action Stocker les détails afin qu’elle affiche les informations d’un seul album. Ajoutez une instruction « using » en haut de la classe StoreControllers pour inclure l’espace de noms MvcMusicStore.Models. Nous n’avons donc pas besoin de taper MvcMusicStore.Models.Album chaque fois que nous voulons utiliser la classe d’album. La section « utilisations » de cette classe doit maintenant apparaître comme suit.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcMusicStore.Models;
Ensuite, nous allons mettre à jour l’action du contrôleur Détails afin qu’elle retourne une actionResult plutôt qu’une chaîne, comme nous l’avons fait avec la méthode Index de HomeController.
public ActionResult Details(int id)
Nous pouvons maintenant modifier la logique pour renvoyer un objet Album à la vue. Plus loin dans ce tutoriel, nous allons récupérer les données d’une base de données, mais pour l’instant, nous allons utiliser les « données factices » pour commencer.
public ActionResult Details(int id)
{
var album = new Album { Title = "Album " + id };
return View(album);
}
Remarque : Si vous n’êtes pas familiarisé avec C#, vous pouvez supposer que l’utilisation de var signifie que notre variable d’album est liée en retard. Ce n’est pas correct : le compilateur C# utilise l’inférence de type en fonction de ce que nous affectons à la variable pour déterminer que l’album est de type Album et compiler la variable d’album locale en tant que type Album. Nous obtenons donc la vérification au moment de la compilation et la prise en charge de l’éditeur de code Visual Studio.
Nous allons maintenant créer un modèle d’affichage qui utilise notre album pour générer une réponse HTML. Avant de le faire, nous devons générer le projet afin que la boîte de dialogue Ajouter une vue connaisse notre classe Album nouvellement créée. Vous pouvez générer le projet en sélectionnant l’élément de menu Debug⇨Build MvcMusicStore (pour un crédit supplémentaire, vous pouvez utiliser le raccourci Ctrl-Maj-B pour générer le projet).
Maintenant que nous avons configuré nos classes de prise en charge, nous sommes prêts à créer notre modèle View. Cliquez avec le bouton droit dans la méthode Details et sélectionnez « Ajouter un affichage... » dans le menu contextuel.
Nous allons créer un modèle d’affichage comme nous l’avons fait auparavant avec le HomeController. Étant donné que nous le créons à partir du StoreController, il sera généré par défaut dans un fichier \Views\Store\Index.cshtml.
Contrairement auparavant, nous allons case activée la case à cocher « Créer un affichage fortement typé ». Nous allons ensuite sélectionner notre classe « Album » dans la liste déroulante « Afficher la classe de données ». Ainsi, la boîte de dialogue « Ajouter une vue » crée un modèle d’affichage qui s’attend à ce qu’un objet Album lui soit passé pour l’utiliser.
Lorsque nous cliquons sur le bouton « Ajouter », notre modèle de vue \Views\Store\Details.cshtml est créé, contenant le code suivant.
@model MvcMusicStore.Models.Album
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
Notez la première ligne, qui indique que cette vue est fortement typée dans notre classe Album. Le moteur de vue Razor comprend qu’il a été passé à un objet Album, ce qui nous permet d’accéder facilement aux propriétés du modèle et même de bénéficier d’IntelliSense dans l’éditeur Visual Web Developer.
Mettez à jour la <balise h2> afin qu’elle affiche la propriété Title de l’album en modifiant cette ligne comme suit.
<h2>Album: @Model.Title</h2>
Notez qu’IntelliSense est déclenché lorsque vous entrez la période après le @Model mot clé, en affichant les propriétés et méthodes prises en charge par la classe Album.
Réexécutons maintenant notre projet et accédons à l’URL /Store/Details/5. Nous verrons les détails d’un album comme ci-dessous.
Nous allons maintenant effectuer une mise à jour similaire pour la méthode d’action Store Browse. Mettez à jour la méthode pour qu’elle retourne un Objet ActionResult et modifiez la logique de la méthode afin qu’elle crée un objet Genre et le retourne à la vue.
public ActionResult Browse(string genre)
{
var genreModel = new Genre { Name = genre };
return View(genreModel);
}
Cliquez avec le bouton droit dans la méthode Parcourir et sélectionnez « Ajouter une vue... » dans le menu contextuel, ajoutez une vue fortement typée, ajoutez un fortement typé à la classe Genre.
Mettez à jour l’élément <h2> dans le code de la vue (dans /Views/Store/Browse.cshtml) pour afficher les informations genre.
@model MvcMusicStore.Models.Genre
@{
ViewBag.Title = "Browse";
}
<h2>Browsing Genre: @Model.Name</h2>
Nous allons maintenant réexécuter notre projet et accéder à /Store/Browse? Genre=URL disco. La page Parcourir s’affiche comme ci-dessous.
Enfin, nous allons effectuer une mise à jour légèrement plus complexe de la méthode d’action Store Index et de la vue pour afficher une liste de tous les genres dans notre magasin. Pour ce faire, nous utiliserons une liste de genres comme objet de modèle, plutôt qu’un seul genre.
public ActionResult Index()
{
var genres = new List<Genre>
{
new Genre { Name = "Disco"},
new Genre { Name = "Jazz"},
new Genre { Name = "Rock"}
};
return View(genres);
}
Cliquez avec le bouton droit dans la méthode d’action Stocker l’index, sélectionnez Ajouter une vue comme avant, sélectionnez Genre comme classe Modèle, puis appuyez sur le bouton Ajouter.
Tout d’abord, nous allons modifier la @model déclaration pour indiquer que la vue attend plusieurs objets Genre plutôt qu’un seul. Modifiez la première ligne de /Store/Index.cshtml comme suit :
@model IEnumerable<MvcMusicStore.Models.Genre>
Cela indique au moteur d’affichage Razor qu’il travaillera avec un objet de modèle pouvant contenir plusieurs objets Genre. Nous utilisons un genre> IEnumerable<plutôt qu’un genre> de liste<, car il est plus générique, ce qui nous permet de changer ultérieurement notre type de modèle en n’importe quel type d’objet qui prend en charge l’interface IEnumerable.
Ensuite, nous allons parcourir les objets Genre dans le modèle, comme indiqué dans le code de vue terminé ci-dessous.
@model IEnumerable<MvcMusicStore.Models.Genre>
@{
ViewBag.Title = "Store";
}
<h3>Browse Genres</h3>
<p>
Select from @Model.Count()
genres:</p>
<ul>
@foreach (var genre in Model)
{
<li>@genre.Name</li>
}
</ul>
Notez que nous avons une prise en charge complète d’IntelliSense lorsque nous entrons ce code, de sorte que lorsque nous tapons « @Model », nous voyons toutes les méthodes et propriétés prises en charge par un IEnumerable de type Genre.
Dans notre boucle « foreach », Visual Web Developer sait que chaque élément est de type Genre. Nous voyons donc IntelliSense pour chacun du type Genre.
Ensuite, la fonctionnalité de génération automatique a examiné l’objet Genre et a déterminé que chacun d’eux aura une propriété Name, de sorte qu’il effectue une boucle et les écrit. Il génère également des liens Modifier, Détails et Supprimer vers chaque élément individuel. Nous en profiterons plus tard dans notre responsable de magasin, mais pour l’instant, nous aimerions avoir une liste simple à la place.
Lorsque nous exécutons l’application et accédons à /Store, nous constatons que le nombre et la liste des genres s’affichent.
Ajout de liens entre les pages
Notre URL /Store qui répertorie genres répertorie actuellement les noms de genre simplement en texte brut. Nous allons changer cela afin qu’au lieu de texte brut, nous ayons plutôt le lien Noms de genre vers l’URL /Store/Browse appropriée, afin que le fait de cliquer sur un genre de musique comme « Disco » accède à l’URL /Store/Browse?genre=Disco. Nous pouvons mettre à jour notre modèle d’affichage \Views\Store\Index.cshtml pour générer ces liens à l’aide de code comme ci-dessous (ne tapez pas ceci dans , nous allons l’améliorer) :
<ul>
@foreach (var genre in Model)
{
<li><a href="/Store/Browse?genre=@genre.Name">@genre.Name</a></li>
}
</ul>
Cela fonctionne, mais cela pourrait entraîner des problèmes plus tard, car il s’appuie sur une chaîne codée en dur. Par instance, si nous voulions renommer le contrôleur, nous devons rechercher dans notre code les liens qui doivent être mis à jour.
Une autre approche que nous pouvons utiliser consiste à tirer parti d’une méthode d’assistance HTML. ASP.NET MVC inclut des méthodes d’assistance HTML disponibles à partir de notre code de modèle d’affichage pour effectuer diverses tâches courantes comme suit. La méthode d’assistance Html.ActionLink() est particulièrement utile et facilite la création de liens HTML <> et prend en charge les détails ennuyeux, comme s’assurer que les chemins d’URL sont correctement codés sur l’URL.
Html.ActionLink() a plusieurs surcharges différentes pour permettre de spécifier autant d’informations que nécessaire pour vos liens. Dans le cas le plus simple, vous devez fournir uniquement le texte du lien et la méthode Action à utiliser lorsque vous cliquez sur le lien hypertexte sur le client. Par exemple, nous pouvons lier la méthode « /Store/ » Index() sur la page Détails du Store avec le texte de lien « Accéder à l’index du Store » à l’aide de l’appel suivant :
@Html.ActionLink("Go
to the Store Index", "Index")
Remarque : Dans ce cas, nous n’avons pas eu besoin de spécifier le nom du contrôleur, car nous créons simplement une liaison à une autre action dans le même contrôleur que celui qui affiche la vue actuelle.
Nos liens vers la page Parcourir devront toutefois passer un paramètre. Nous allons donc utiliser une autre surcharge de la méthode Html.ActionLink qui prend trois paramètres :
-
- Texte du lien, qui affiche le nom du genre
-
- Nom de l’action du contrôleur (Parcourir)
-
- Valeurs des paramètres de routage, en spécifiant à la fois le nom (Genre) et la valeur (Nom de genre)
En mettant tout cela ensemble, voici comment nous allons écrire ces liens dans la vue Index du Store :
<ul>
@foreach (var genre in Model)
{
<li>@Html.ActionLink(genre.Name,
"Browse", new { genre = genre.Name })</li>
}
</ul>
À présent, lorsque nous réexécutons notre projet et accédons à l’URL /Store/, nous voyons une liste des genres. Chaque genre est un lien hypertexte. Lorsque vous cliquez dessus, il nous amène à notre URL /Store/Browse?genre=[genre].
Le code HTML de la liste des genres ressemble à ceci :
<ul>
<li><a href="/Store/Browse?genre=Disco">Disco</a>
</li>
<li><a href="/Store/Browse?genre=Jazz">Jazz</a>
</li>
<li><a href="/Store/Browse?genre=Rock">Rock</a>
</li>
</ul>