Passage de données à des pages maîtres de vue (C#)
par Microsoft
L’objectif de ce tutoriel est d’expliquer comment passer des données d’un contrôleur à une vue master page. Nous examinons deux stratégies pour transmettre des données à une vue master page. Tout d’abord, nous discutons d’une solution simple qui aboutit à une application difficile à gérer. Ensuite, nous examinons une solution bien meilleure qui nécessite un peu plus de travail initial, mais aboutit à une application beaucoup plus facile à gérer.
Passage de données pour afficher les pages maîtres
L’objectif de ce tutoriel est d’expliquer comment passer des données d’un contrôleur à une vue master page. Nous examinons deux stratégies pour transmettre des données à une vue master page. Tout d’abord, nous discutons d’une solution simple qui aboutit à une application difficile à gérer. Ensuite, nous examinons une solution bien meilleure qui nécessite un peu plus de travail initial, mais aboutit à une application beaucoup plus facile à gérer.
Le problème
Imaginez que vous créez une application de base de données de films et que vous souhaitez afficher la liste des catégories de films sur chaque page de votre application (voir la figure 1). En outre, imaginez que la liste des catégories de films est stockée dans une table de base de données. Dans ce cas, il serait judicieux de récupérer les catégories de la base de données et d’afficher la liste des catégories de films dans une vue master page.
Figure 01 : Affichage des catégories de films dans un affichage master page (Cliquer pour afficher l’image en taille réelle)
Voici le problème. Comment récupérer la liste des catégories de films dans la page master ? Il est tentant d’appeler directement les méthodes de vos classes de modèle dans la page master. En d’autres termes, il est tentant d’inclure le code permettant de récupérer les données de la base de données directement dans votre page de master. Toutefois, le contournement de vos contrôleurs MVC pour accéder à la base de données violerait la séparation propre des problèmes qui est l’un des principaux avantages de la création d’une application MVC.
Dans une application MVC, vous souhaitez que toutes les interactions entre vos vues MVC et votre modèle MVC soient gérées par vos contrôleurs MVC. Cette séparation des préoccupations entraîne une application plus facile à gérer, adaptable et testable.
Dans une application MVC, toutes les données transmises à une vue, y compris une vue master page, doivent être passées à une vue par une action de contrôleur. En outre, les données doivent être transmises en tirant parti des données d’affichage. Dans le reste de ce tutoriel, j’examine deux méthodes de transmission de données d’affichage à une vue master page.
La solution simple
Commençons par la solution la plus simple pour passer des données d’affichage d’un contrôleur à une vue master page. La solution la plus simple consiste à passer les données d’affichage de la page master dans chaque action du contrôleur.
Considérez le contrôleur dans la liste 1. Il expose deux actions nommées Index()
et Details()
. La Index()
méthode d’action retourne chaque film de la table de base de données Movies. La Details()
méthode d’action retourne chaque film d’une catégorie de film particulière.
Listing 1 – Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
private MovieDataContext _dataContext = new MovieDataContext();
/// <summary>
/// Show list of all movies
/// </summary>
public ActionResult Index()
{
ViewData["categories"] = from c in _dataContext.MovieCategories
select c;
ViewData["movies"] = from m in _dataContext.Movies
select m;
return View();
}
/// <summary>
/// Show list of movies in a category
/// </summary>
public ActionResult Details(int id)
{
ViewData["categories"] = from c in _dataContext.MovieCategories
select c;
ViewData["movies"] = from m in _dataContext.Movies
where m.CategoryId == id
select m;
return View();
}
}
}
Notez que les actions Index() et Details() ajoutent deux éléments pour afficher les données. L’action Index() ajoute deux clés : catégories et films. La clé catégories représente la liste des catégories de films affichées par l’affichage master page. La clé movies représente la liste des films affichés par la page Affichage d’index.
L’action Détails() ajoute également deux touches nommées catégories et films. La clé catégories, une fois de plus, représente la liste des catégories de films affichées par l’affichage master page. La touche Movies représente la liste des films d’une catégorie particulière affichée par la page d’affichage Détails (voir la figure 2).
Figure 02 : Affichage Détails (cliquer pour afficher l’image en taille réelle)
La vue Index est contenue dans la liste 2. Il effectue simplement une itération dans la liste des films représentés par l’élément de films dans les données d’affichage.
Listing 2 – Views\Home\Index.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<ul>
<% foreach (var m in (IEnumerable<Movie>)ViewData["movies"])
{ %>
<li><%= m.Title %></li>
<% } %>
</ul>
</asp:Content>
La page d’affichage master figure dans la liste 3. L’affichage master page itère et restitue toutes les catégories de films représentées par l’élément catégories à partir des données d’affichage.
Listing 3 – Views\Shared\Site.master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Master.cs" Inherits="MvcApplication1.Views.Shared.Site" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<div>
<h1>My Movie Website</h1>
<% foreach (var c in (IEnumerable<MovieCategory>)ViewData["categories"])
{%>
<%= Html.ActionLink(c.Name, "Details", new {id=c.Id} ) %>
<% } %>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
Toutes les données sont passées à l’affichage et l’affichage master page à travers les données d’affichage. Il s’agit de la bonne façon de transmettre des données à la page master.
Alors, qu’est-ce qui ne va pas avec cette solution ? Le problème est que cette solution viole le principe DRY (Don’t Repeat Yourself). Chaque action de contrôleur doit ajouter la même liste de catégories de films pour afficher les données. Le fait d’avoir du code en double dans votre application rend votre application beaucoup plus difficile à gérer, à adapter et à modifier.
La bonne solution
Dans cette section, nous examinons une solution alternative et meilleure pour passer des données d’une action de contrôleur à une vue master page. Au lieu d’ajouter les catégories de films pour la page master dans chaque action de contrôleur, nous ajoutons les catégories de films aux données d’affichage une seule fois. Toutes les données d’affichage utilisées par la page de master d’affichage sont ajoutées dans un contrôleur d’application.
La classe ApplicationController est contenue dans listing 4.
Listing 4 – Controllers\ApplicationController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public abstract class ApplicationController : Controller
{
private MovieDataContext _dataContext = new MovieDataContext();
public MovieDataContext DataContext
{
get { return _dataContext; }
}
public ApplicationController()
{
ViewData["categories"] = from c in DataContext.MovieCategories
select c;
}
}
}
Vous devez remarquer trois choses concernant le contrôleur d’application dans la liste 4. Tout d’abord, notez que la classe hérite de la classe System.Web.Mvc.Controller de base. Le contrôleur d’application est une classe de contrôleur.
Ensuite, notez que la classe du contrôleur Application est une classe abstraite. Une classe abstraite est une classe qui doit être implémentée par une classe concrète. Étant donné que le contrôleur d’application est une classe abstraite, vous ne pouvez pas appeler directement des méthodes définies dans la classe. Si vous tentez d’appeler la classe Application directement, vous obtenez un message d’erreur Ressource introuvable.
Troisièmement, notez que le contrôleur d’application contient un constructeur qui ajoute la liste des catégories de films pour afficher les données. Chaque classe de contrôleur qui hérite du contrôleur d’application appelle automatiquement le constructeur du contrôleur d’application. Chaque fois que vous appelez une action sur un contrôleur qui hérite du contrôleur d’application, les catégories de films sont automatiquement incluses dans les données d’affichage.
Le contrôleur Movies dans la liste 5 hérite du contrôleur d’application.
Listing 5 – Controllers\MoviesController.cs
using System.Linq;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class MoviesController : ApplicationController
{
/// <summary>
/// Show list of all movies
/// </summary>
public ActionResult Index()
{
ViewData["movies"] = from m in DataContext.Movies
select m;
return View();
}
/// <summary>
/// Show list of movies in a category
/// </summary>
public ActionResult Details(int id)
{
ViewData["movies"] = from m in DataContext.Movies
where m.CategoryId == id
select m;
return View();
}
}
}
Le contrôleur Movies, tout comme le contrôleur d’accueil décrit dans la section précédente, expose deux méthodes d’action nommées Index()
et Details()
. Notez que la liste des catégories de films affichées par l’affichage master page n’est pas ajoutée pour afficher les données dans la Index()
méthode ou Details()
. Étant donné que le contrôleur Movies hérite du contrôleur d’application, la liste des catégories de films est ajoutée pour afficher automatiquement les données.
Notez que cette solution pour ajouter des données d’affichage pour un affichage master page ne viole pas le principe DRY (Don’t Repeat Yourself). Le code permettant d’ajouter la liste des catégories de films pour afficher les données est contenu dans un seul emplacement : le constructeur du contrôleur d’application.
Résumé
Dans ce tutoriel, nous avons abordé deux approches pour passer des données d’affichage d’un contrôleur à une vue master page. Tout d’abord, nous avons examiné une approche simple, mais difficile à maintenir. Dans la première section, nous avons expliqué comment ajouter des données d’affichage pour une vue master page dans chaque action de contrôleur dans votre application. Nous avons conclu qu’il s’agissait d’une mauvaise approche, car elle violait le principe DRY (Don’t Repeat Yourself).
Ensuite, nous avons examiné une stratégie bien meilleure pour ajouter des données requises par une vue master page pour afficher les données. Au lieu d’ajouter les données d’affichage dans chaque action du contrôleur, nous n’avons ajouté les données d’affichage qu’une seule fois au sein d’un contrôleur d’application. De cette façon, vous pouvez éviter le code en double lors du passage de données à une page master d’affichage dans une application MVC ASP.NET.