• 30 hours
  • Medium

Free online content available in this course.

Certificate of achievement available at the end this course

You can get support and mentoring from a private teacher via videoconference on this course.

Got it!

Last updated on 11/23/17

Les moteurs de vues

Log in or subscribe for free to enjoy all this course has to offer!

Du M, du V et du C, ça… on en a mangé un bon paquet. J’espère que ceci n’a pas été trop dur à digérer car il vous faut toute votre énergie pour passer à la suite ! En effet, ASP.NET MVC c’est un peu plus que l’application d’un simple patron de conception. Nous allons découvrir dans cette partie d’autres éléments qui viennent se greffer tout naturellement sur nos applications web et pour lesquels ASP.NET MVC a prévu une solution puissante et robuste.
Vous allez découvrir plein de belles choses que je ne saurais toutes vous citer, de peur que vous ne sachiez par quel chapitre commencer, paralysés par l'envie d'apprendre. :p Au hasard, un peu d’Ajax… un peu de site mobiles… Stop, je n’en dis pas plus et je vous laisse découvrir les subtilités du moteur de vue.

Le moteur de vue historique ASPX

Jusqu’à présent, pour écrire nos vues, nous avons utilisé du HTML agrémenté de C#, préfixé par le caractère @. Vous avez donc utilisé le moteur de vues que l'on appelle Razor pour écrire vos vues.

Ce moteur de vue est plutôt récent dans la mesure où il a été créé en 2010. Le but de l'implémentation de Razor était de fournir une syntaxe optimisée pour l'écriture des vues ASP.NET MVC avec une syntaxe qui ressemble aux syntaxes des moteurs de template. Vous ne vous en rendez sans doute pas compte, car vous venez de démarrer l'apprentissage d'ASP.NET MVC 5 avec Visual Studio 2013, mais vous partez avec un sérieux avantage. Celui de démarrer votre apprentissage avec Razor !!

Parce qu'avant Razor, au début d'ASP.NET MVC (2008), il y avait le moteur de vue ASPX.

C'est le moteur de vue historique qui existe depuis le tout début d'ASP.NET MVC. La syntaxe du moteur de vue ASPX est même encore plus vieille car c'est la syntaxe utilisée par la toute première version d'ASP.NET WebForms, qui date de 2002... On le reconnait très facilement parce qu’il est plein de <% et de %> délimitant les zones où l’on peut écrire du code C#.

Jusqu'à la version 2012 de Visual Studio, il était possible de choisir de créer une vue utilisant soit le moteur de vue ASPX, soit le moteur de vue Razor ; ce dernier étant mis en valeur par rapport à l'autre. Disons plus précisément qu'avant, lorsqu'on créait une vue, on avait une liste déroulante qui nous permettait de faire ce choix :

Choix du moteur de vue, avant Visual Studio 2013
Choix du moteur de vue, avant Visual Studio 2013

Cependant, depuis Visual Studio 2013, il n'est plus possible de créer une vue utilisant le moteur de vue ASPX. Lorsque nous ajoutons une nouvelle vue, nous ajoutons directement une vue Razor.

Un petit aperçu du moteur de vue ASPX

Et franchement, ce n'est pas plus mal. Allez, pour le plaisir, je vous donne un petit aperçu de l'équivalent de ce que nous avons appris en Razor en ASPX.

Par exemple pour afficher un simple message dans du HTML, avec Razor nous faisons :

<p>@ViewBag.Message</p>

Alors qu'avec ASPX, on aurait fait :

<p><%:ViewBag.Message %></p>

Ici, ça ne fait pas trop peur, mais si on veut faire un HTML un peu plus enrichi, on aurait en Razor :

<p>Bonjour @ViewBag.Prenom vous avez @ViewBag.Age ans</p>

Alors qu'avec ASPX :

<p>Bonjour <%:ViewBag.Prenom%> vous avez <%:@ViewBag.Age%> ans</p>

Ça commence déjà à s'alourdir.

Alors imaginez avec plein de if  ou foreach... Voici avec Razor :

<table>
    <tr>
        <th>Nom</th>
        <th>Age</th>
    </tr>
    @{
        int i = 0;
        foreach (HelloWorld.Models.Client client in Model)
        {
            <tr>
                @if (i % 2 == 0)
                {
                    <td style="background-color:gray">@client.Nom</td>
                    <td style="background-color:gray">@client.Age</td>
                }
                else
                {
                    <td style="background-color:darkgray">@client.Nom</td>
                    <td style="background-color:darkgray">@client.Age</td>
                }
            </tr>
            i++;
        }
    }
</table>

et avec ASPX :

<table>
    <tr>
        <th>Nom</th>
        <th>Age</th>
    </tr>
    <% 
        int i = 0;
        foreach (HelloWorld.Models.Client client in Model)
        {
    %>
    <tr>
        <% 
                if (i % 2 == 0)
                {
        %>
        <td style="background-color: gray"><%: client.Nom%></td>
        <td style="background-color: gray"><%: client.Age%></td>
        <%      }   
                else
                {
        %>
        <td style="background-color: darkgray"><%: client.Nom%></td>
        <td style="background-color: darkgray"><%: client.Age%></td>
        <%      }
        %>
    </tr>
    <% 
            i++;
        }
    %>
</table>

à en perdre son latin... Et encore, vous vous doutez que dès qu'on va rajouter un petit formulaire avec quelques helpers et des validations, ça va vite devenir le bazar !

Pourquoi un nouveau moteur de vue ?

Vous vous en êtes bien rendu compte en lisant le paragraphe précédent, le moteur de vue ASPX possède un gros défaut. Si nous commençons à faire des vues un peu complexes, elles deviennent tout de suite illisibles. On le constate particulièrement avec l'exemple du tableau juste avant qui possède une couleur différente par ligne.

Déjà, on commence à avoir plein de <% et de %>, sans parler de l’indentation. On perd tout de suite en lisibilité… OK, on arrive à comprendre, mais rajoutez-y quelques if qui vont permettre soit d’afficher ce tableau, soit un graphique en fonction du choix de l’utilisateur et ça devient carrément illisible.

C’est un des gros reproches qui a été fait à ASP.NET MVC avec ce sentiment de revenir à de l’ASP (avant ASP.NET !) voire à du vieux PHP. Voilà pourquoi Razor est né. Son but est de permettre d'écrire des vues de la manière la plus fluide possible sans avoir l'impression d'écrire du HTML et du C#. Les transitions sont les plus naturelles possibles, dès qu'on veut écrire du code, il y a juste à utiliser le @ et puis voilà. Tout est fait pour que le développeur ait l'impression d'écrire dans un seul et unique langage.

C'est donc tout naturellement qu'aujourd'hui c'est Razor qui est majoritairement utilisé par tout le monde et que le moteur de vue ASPX est de plus en plus abandonné. Vous voyez même qu'il n'est plus possible de créer une vue ASPX avec Visual Studio 2013. Mais que les fans d'ASPX se rassurent, la compatibilité est assurée, ce qui est primordial lorsqu'on effectue une migration d'un site web. Mais pensez quand même à Razor... une fois essayé, il est adopté. ;)

Pas besoin de réfléchir à quelque chose de compliqué, il faut écrire vos vues sans penser qu’il y a du HTML et du Razor... 

Quelques spécificités de Razor

Globalement, Razor est assez intelligent pour faire tout ce que l’on souhaite. Il y a bien sûr des subtilités dues à la légèreté de la syntaxe. Par exemple, pour affiche le nom d’un resto, nous avons vu que nous pouvions faire :

<table>
    <tr>
        <th>Nom</th>
        <th>Téléphone</th>
    </tr>
    @foreach (var resto in Model)
    {
        <tr>
            <td>@resto.Nom</td>
            <td>@resto.Telephone</td>
        </tr>
    }
</table>

Avec la syntaxe @resto.Nom , Razor en déduit que nous souhaitons afficher la propriété Nom de l’objet resto ; grâce au point, comme on le ferait dans du C#. Mais comment faire si nous souhaitons afficher un point juste après le nom du restaurant, de manière à avoir un truc du genre : « Le nom du restaurant est Resto Pinière. ». Il suffira d’écrire :

<td>Le nom est : @resto.Nom.</td>

Pas de problème. Ici, Razor a compris tout naturellement que le point final ne sert pas à accéder à une propriété car derrière il s’agit d’une balise HTML alors que le premier point sert à accéder à la propriété du resto.
Par contre, si nous enchaînons tout de suite avec un littéral, de cette manière :

<td>Le nom est : @resto.Nom.Voilà !</td>

Nous avons un problème car Voilà  n’est pas une propriété de Nom . OK, en temps normal nous n’aurions jamais fait ça car notre belle langue impose de mettre un espace après un point. Mais pour X raisons, nous pourrions trouver un élément de ce genre. Dans ce cas, nous pourrons encadrer l’expression avec des parenthèses :

<td>Le nom est : @(resto.Nom).Voilà !</td>

pour résoudre le problème.

De même, Razor détecte certaines expressions particulières. Le cas de l’email par exemple, possédant un @ au milieu. Rien besoin de faire de spécial, nous pouvons écrire :

<p>Envoyez-moi un mail sur mail@domaine.com</p>

Ici, Razor comprends qu’il s’agit d’une adresse email et pas d’un objet domaine où nous souhaitons afficher la propriété com… Malin ! ;)

D’ailleurs, si nous souhaitons simplement afficher un @, il faudra le doubler :

<p>Ça ne marche pas !!! @@#!{?@@# !</p>

Ce qui affichera :

Ça ne marche pas !!! @#!{?@# !

Par contre, Razor détecte bien souvent une transition entre sa syntaxe et le HTML grâce aux balises HTML. Ceci est donc tout à fait valide :

@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    <div>C'est le week-end</div>
}
else
{
    <div>C'est la semaine</div>
}

On pourrait penser pouvoir s’éviter deux div  en sortant les div  du if , ce qui donnerait :

<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    C'est le week-end
}
else
{
    C'est la semaine
}
</div>

Sauf que là, ça ne marche plus. Bien sûr, Razor croit que c’est du C#… et ce C# n’est pas tout à fait valide. :p
Pour corriger ceci, il existe deux solutions. La première est d’utiliser la balise spéciale <text>  afin de dire à Razor que nous souhaitons afficher du texte :

<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    <text>C'est le week-end</text>
}
else
{
    <text>C'est la semaine</text>
}
</div>

Cette balise étant spéciale, elle n’est pas rendue dans le HTML final (car ce n’est pas une vraie balise), et nous aurons :

<div>
C’est le week-end
</div>

L’autre solution est de préfixer le texte par un @:, pour avoir :

<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    @:C'est le week-end
}
else
{
    @:C'est la semaine
}
</div>

Pour info, pour avoir la même chose avec le moteur de vue ASPX, nous aurions fait :

<div>
    <% if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
        {
    %>
    C'est le week-end
    <%}
        else
        {
    %>
    C'est la semaine
    <%
        } %>
</div>

Aïe mes yeux. ^^

Vous l'avez vu vite fait dans le chapitre sur les validations, mais je n'en ai pas encore officiellement parlé. Il est très facile d’écrire des commentaires dans une vue Razor. On utilise le @* pour démarrer un commentaire et le *@ pour le terminer :

Ainsi pour mettre en commentaire notre précédent élément de code, nous pourrons faire :

@*<div>
@if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
    @:C'est le week-end
}
else
{
    @:C'est la semaine
}
</div>*@

À noter qu’avec le moteur de vue ASPX, on n’est pas loin :

<%--    <div>
        <% if (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
           {
        %>
        C'est le week-end
        <%}
           else
           {
        %>
        C'est la semaine
        <%
           } %>
    </div>--%>

Les layout

Jusqu’à présent, nos vues ont été responsables de gérer tout le HTML qui s’affiche dans le navigateur, balise <head> , balise <body> , etc. Heureusement, jusqu’à présent nos vues ont été plutôt relativement légères en terme de contenu HTML, ceci pour simplifier au maximum notre apprentissage et ne pas nous encombrer de plein de choses. Mais une application web, c’est rarement ça. Vous avez bien souvent en haut un titre de page, un logo, une bannière, qui se répètent sur toutes les pages. De même, vous avez bien souvent un menu pour accéder aux différents éléments du site. Nous retrouvons généralement un pied de page aussi, qui contient les mentions légales, le copyright, des infos de contact, etc.
Bref, il y a beaucoup de choses qui se répètent dans toutes les pages du site. Certaines ne varient pas, comme le logo ou la bannière, voire le copyright. Certaines peuvent varier légèrement, comme le menu qui bien souvent montre en surbrillance l’élément de menu sur lequel nous nous trouvons.

Je vous le demande :

est-ce que nous sommes suffisamment fous pour répéter à la main tous ces éléments à travers toutes nos vues ?

Je vous rassure tout de suite, la réponse est non !
Ok, le copier-coller ça marche, mais si jamais je dois changer quelque chose, il faut que je le change partout… Sans parler du risque d’erreur et de la contre-motivation que cela engendre.

Vous allez être fous, oui… Mais simplement fous de joie, de constater qu’ASP.NET MVC ne nous laisse pas dans la panade et nous offre un concept bien plaisant que l’on appelle les Layout, que l’on peut traduire par « disposition », ce que nous ne ferons pas. ;)
Si vous avez déjà fait un peu d’ASP.NET WebForms, vous connaissez sans doute les Master Pages. Eh bien, les Layout, c’est le même principe mais version Razor.

Prenons par exemple un site où j’essaie de faire en sorte d’avoir un contenu qui se répète entre les pages. On va prendre pour l’exemple un site de tutoriels de mon cru, tellement joli que vous allez m’envier mes compétences en Paint et en choix de couleurs :

Les layouts d'ASP.NET MVC
Les layouts d'ASP.NET MVC

Ça fait envie non ? :p
Le but était d’avoir des zones clairement identifiées et délimitées. Voici le contenu de ma vue Index :

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <style type="text/css">
        #entete, #menu, #contenu, #footer {
            padding: 1px 0;
        }

        #entete {
            background-color: lightcoral;
            text-align: center;
            background: #FF9900 url("/Content/Images/supertuto.png") 5px center no-repeat;
            background-size: 100px;
        }

        #main {
            margin: auto;
        }

        #menu {
            float: left;
            width: 240px;
            background-color: lightsalmon;
        }

        #contenu {
            margin-left: 245px;
            background-color: lightblue;
        }

        #footer {
            background-color: lightgreen;
            text-align: center;
            clear: both;
        }

        .titre {
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="entete">
        <h1>Bienvenue sur Super tuto</h1>
    </div>

    <div id="main">
        <div id="menu">
            <ul>
                <li>@Html.ActionLink("Accueil", "Index")</li>
                <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                <li>@Html.ActionLink("Forum", "Forum")</li>
            </ul>
        </div>

        <div id="contenu">
            <h3 class="titre">Accueil du site de tutoriels</h3>
            <p class="contenu">Ici c'est la page d'accueil avec les news du site, etc.</p>
        </div>
    </div>

    <div id="footer">
        &copy; @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com
    </div>
</body>
</html>

Vous aurez compris que je vais faire en sorte de garder tout le contour et que c’est uniquement la zone lightblue du milieu qui va changer. Celle-ci prendra le contenu de accueil, puis le contenu de la liste des tutoriels, puis le contenu du forum, en fonction de la vue que nous affichons.

Première chose qu’on peut faire pour alléger un peu mes copier-coller, c’est de mettre tout le style dans un fichier CSS à part. J’ai donc créé un fichier supertuto.css avec tout ce CSS dans le répertoire Content et je peux supprimer ma balise style pour la remplacer par :

<link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />

Maintenant, nous allons faire des modifications sur la vue Index. Ce n’est pas elle qui doit porter le contenu qui ne change pas. Nous allons définir ce modèle à part et la vue Index va simplement en hériter. Premièrement, créez un répertoire Shared sous le répertoire Views et faites un clic droit sur le répertoire Shared ; puis ajoutez une page de disposition MVC5 (Razor), que vous pouvez appeler LayoutDuSite.cshtml :

Ajouter une page de disposition
Ajouter une page de disposition

Visual Studio nous génère le contenu suivant :

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Nous commençons à sentir le principe général. Le titre pourra être dynamique grâce à la propriété Title  du ViewBag  ; de même pour le reste du HTML qui sera alimenté par la méthode RenderBody .

Nous allons maintenant modifier ce layout pour y mettre un peu du HTML que nous avons préalablement réalisé :

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
</head>
<body>
    <div id="entete">
        <h1>Bienvenue sur Super tuto</h1>
    </div>

    <div id="main">
        <div id="menu">
            <ul>
                <li>@Html.ActionLink("Accueil", "Index")</li>
                <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
                <li>@Html.ActionLink("Forum", "Forum")</li>
            </ul>
        </div>

        <div id="contenu">
            @RenderBody()
        </div>
    </div>

    <div id="footer">
        &copy; @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com
    </div>
</body>
</html>

Je ne touche pas à la balise <title> qui doit rester dynamique et voyez où j’ai inséré la méthode RenderBody()  : à la place du contenu que je réservais à la vue d’accueil.
Maintenant, je n’ai plus qu’à modifier la vue Index pour supprimer tout ce qu’il y a et y mettre uniquement ceci :

@{
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
    ViewBag.Title = "Accueil";
}

<h3 class="titre">Accueil du site de tutoriels</h3>
<p class="contenu">Ici c'est la page d'accueil avec les news du site, etc.</p>

Cette vue est du coup beaucoup plus concise. Il n’y a qu’un peu de C# et juste les balises que je souhaite afficher dans la zone prévue pour.
Le C# consiste à initialiser la propriété WebPageBase.Layout  permettant de définir le chemin d’accès de la page de layout.
Il suffit ici d’indiquer le chemin de la page que l’on vient de créer. De même, c’est l’emplacement idéal pour indiquer le titre de la page, qui ne bouge jamais. Si le titre était un peu plus dynamique, alors il pourrait être judicieux de l’initialiser dans le contrôleur, mais là on montre clairement l’intention de la page et utiliser le ViewBag  nous permet d’inclure du contenu dynamique dans le layout.

Bien sûr, pour notre vue Liste.cshtml, je vais utiliser exactement le même principe. Créons donc cette vue. Il est possible de choisir directement quel layout notre vue va utiliser grâce à la zone prévue pour, dans la fenêtre d’ajout de vue :

Ajout d'une vue avec une disposition
Ajout d'une vue avec une disposition

Ainsi Visual Studio me génère directement une vue réduite :

@{
    ViewBag.Title = "Liste";
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}

<h2>Liste</h2>

Et j’ai juste à mettre ce que je veux dedans. Par exemple :

@model List<SuperTuto.Models.Tuto>
@{
    ViewBag.Title = "Liste";
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}
<h3 class="titre">
    Liste des tutoriels
</h3>
<table>
    <tr>
        <th>Tutoriel</th>
        <th>Lien</th>
    </tr>
    @foreach (var tutoriel in Model)
    {
        <tr>
            <td>@tutoriel.Titre</td>
            <td>@Html.ActionLink(tutoriel.Lien, "AfficheTutoriel", new { id = tutoriel.Id })</td>
        </tr>
    }
</table>

Vous avez compris le principe, lorsque je naviguerai sur la vue listant les tutoriels, je bénéficierai automatiquement de la mise en page de mon layout. Tout le reste fonctionne comme auparavant. La déclaration du modèle, son utilisation, etc.

Ajoutons une dernière vue pour le forum :

@{
    ViewBag.Title = "Forum";
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}

<h3>En construction...</h3>

C’est bien, nous avons réduit fortement le code des vues tout en étant certains qu’elles bénéficient toutes de la même mise en page. Mais…. sur chaque vue, nous sommes obligés d’indiquer le layout que nous souhaitons utiliser. C’est vrai qu’il n’y a qu’une seule ligne et que ça ne fait pas beaucoup, mais c’est plutôt redondant. D’une manière générale, il est courant d’avoir un unique layout pour un même site et du coup, nous sommes obligés de le saisir sur toutes les pages.

Heureusement, nous pouvons simplifier les choses grâce à un nouveau fichier qui est exécuté avant toutes les vues. Ce fichier spécial s’appelle _ViewStart.cshtml. Il faut le mettre à la racine du répertoire Views. Et ce n'est pas tout ! Vous pouvez même en créer plusieurs et les mettre dans des répertoires différents afin que chacun s'applique à toutes les vues présentes dans ce répertoire (et dans tous les sous-répertoires, récursivement).

Créons donc ce fichier et mettons-y le contenu suivant :

@{
    Layout = "~/Views/Shared/LayoutDuSite.cshtml";
}

Ainsi, nous allons pouvoir supprimer simplement cette ligne de toutes les vues. Grâce au _ViewStart, chaque vue bénéficiera de ce layout. Plutôt pratique non ?

Remarque : si votre vue est dans un répertoire où s’applique un ViewStart qui positionne un Layout dont vous n’avez pas besoin, vous pouvez toujours redéfinir la propriété Layout  en en-tête de la vue et lui affecter null  :

@{
    Layout = null;
    ViewBag.Title = "Test";
}

<h3>Test...</h3>

C’est bien beau, mais nous n’avons fait que la moitié du chemin… Nous avons réglé le cas du corps de la vue avec RenderBody() , mais le reste ?

Les sections

Pour le reste, ASP.NET MVC nous permet de définir des sections nommées. Au lieu d’appeler RenderBody , il faudra appeler la méthode RenderSection  et lui fournir le nom de la section et si elle est obligatoire ou pas. Profitons-en pour modifier un peu notre menu afin de mettre en valeur l’élément de menu que nous sommes en train de visiter. Je choisis par exemple de mettre en valeur la puce en lui changeant sa couleur :

Mise en valeur de la puce sélectionnée
Mise en valeur de la puce sélectionnée

Pour cela, j’ai simplement rajouté le CSS suivant :

.selectionne {
    color:red
}

Et j’ai modifié mon layout pour avoir :

<div id="menu">
    <ul>
        <li class="selectionne">@Html.ActionLink("Accueil", "Index")</li>
        <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
        <li>@Html.ActionLink("Forum", "Forum")</li>
    </ul>
</div>

Sauf qu’avec ça, peu importe la vue sur laquelle je me trouve, j’aurai toujours la mise en valeur au niveau du premier lien. Sauf si j’utilise des sections. Remplaçons le layout pour avoir :

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
</head>
<body>
    <div id="entete">
        <h1>Bienvenue sur Super tuto</h1>
    </div>

    <div id="main">
        <div id="menu">
            @RenderSection("Menu")
        </div>

        <div id="contenu">
            @RenderBody()
        </div>
    </div>

    <div id="footer">
        &copy; @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com
    </div>
</body>
</html>

Vous voyez qu’à l’intérieur de la balise div  de menu, j’ai ajouté la ligne : @RenderSection("Menu") . Je n’ai plus qu’à définir cette section dans ma vue Accueil :

@{
    ViewBag.Title = "Accueil";
}

<h3 class="titre">Accueil du site de tutoriels</h3>
<p class="contenu">Ici c'est la page d'accueil avec les news du site, etc.</p>

@section Menu
{
    <ul>
        <li class="selectionne">@Html.ActionLink("Accueil", "Index")</li>
        <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
        <li>@Html.ActionLink("Forum", "Forum")</li>
    </ul>
}

On utilise @section  suivi du nom de la section à redéfinir. Je n’ai plus qu’à mettre cette section dans mes autres vues en changeant légèrement le HTML. Pour la liste, je vais simplement changer l’emplacement de la class sur la balise <li>  :

@model List<TestLayout.Models.Tuto>
@{
    ViewBag.Title = "Liste";
}
<h3 class="titre">
    Liste des tutoriels</h3>
<table>
    <tr>
        <th>Tutoriel</th>
        <th>Lien</th>
    </tr>
    @foreach (var tutoriel in Model)
    {
        <tr>
            <td>@tutoriel.Titre</td>
            <td>@Html.ActionLink(tutoriel.Lien, "AfficheTutoriel", new { id = tutoriel.Id})</td>
        </tr>
    }
</table>

@section Menu
{
    <ul>
        <li>@Html.ActionLink("Accueil", "Index")</li>
        <li class="selectionne">@Html.ActionLink("Liste des tutoriels", "Liste")</li>
        <li>@Html.ActionLink("Forum", "Forum")</li>
    </ul>
}

Et pareil pour la vue forum :

@{
    ViewBag.Title = "Forum";
}

<h3>En construction...</h3>

@section Menu
{
    <ul>
        <li>@Html.ActionLink("Accueil", "Index")</li>
        <li>@Html.ActionLink("Liste des tutoriels", "Liste")</li>
        <li class="selectionne">@Html.ActionLink("Forum", "Forum")</li>
    </ul>
}

Ceci me permet de mettre des éléments différents dans chacune de mes vues, très pratique pour adapter le menu ou un footer, ou autre…
En plus, le nombre de sections n’est pas limité, vous pouvez personnaliser vos pages comme bon vous semble.

Je vous ai également dit qu’il était possible de définir si la section était obligatoire ou pas. Avec l’utilisation que nous venons d’en faire :

@RenderSection("Menu")

la section est obligatoire. Cela veut dire que si nous ne définissions pas la section dans une des vues et que nous naviguons sur cette vue, alors ASP.NET MVC lèvera une erreur :

Erreur quand la section est indéfinie
Erreur quand la section est indéfinie

Il est possible de rendre la section facultative en utilisant la méthode RenderSection  de cette façon :

@RenderSection("Menu", required: false)

Ainsi, vous n’êtes plus obligés de définir la section Menu si jamais vous avez une vue où vous ne souhaitez pas l’afficher. Bon… dans notre cas cela va faire un gros trou blanc disgracieux, mais nous pouvons trouver plein de sections potentiellement facultatives.
Nous pouvons d’ailleurs vérifier si une section a été définie et pourquoi pas la remplacer par une valeur par défaut quand ce n’est pas le cas. Il suffit d’utiliser la méthode IsSectionDefined . Nous pourrions par exemple faire pour le footer :

<div id="footer">
    @if (IsSectionDefined("footer"))
    {
        @RenderSection("footer")
    }
    else
    {
        <text>&copy; @DateTime.Now.Year - Super site de tutoriels, contactez moi sur monmail@supersitetutoriels.com</text>
    }
</div>

Cela permettra d’avoir l’opportunité de personnaliser son footer ou bien de prendre la valeur par défaut.
Bien sûr, vous pouvez combiner les sections à la puissance des vues partielles. Imaginons que dans votre site vous ayez la moitié des pages où vous devez définir un footer et l’autre moitié utiliser celui par défaut ; plutôt que de recopier X fois le même footer vous pouvez appeler une vue partielle pour afficher le footer…

Une pratique courante des sections est de définir une section permettant d’inclure des scripts JavaScript ou du CSS depuis le layout et d’insérer les scripts nécessaire à une vue dans cette section. Dans le layout on peut mettre :

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link type="text/css" rel="stylesheet" href="~/Content/supertuto.css" />
    <script type="text/javascript" src="~/Scripts/jquery-1.10.2.js"></script>
    @RenderSection("scripts", required: false)
</head>

Et dans la vue, on aura :

@section scripts
{
<script type="text/javascript">
    $(function () {
        alert('test');
    });
</script>
}

En résumé

  • Razor est le nouveau moteur de vue d’ASP.NET MVC, apparu avec la version 3 d’ASP.NET MVC.

  • ASPX est le moteur de vue historique et n'est plus proposé avec Visual Studio 2013.

  • Razor permet de simplifier l’écriture des vues par rapport à ASPX en bénéficiant de transitions plus légères entre les balises et le code C#.

  • On peut définir un modèle à appliquer à toutes les vues d’un site grâce aux layouts.

  • Les sections sont un complément des layouts et permettent de redéfinir des zones prédéfinies dans les vues qui héritent d’un layout.

Example of certificate of achievement
Example of certificate of achievement