Comment mettre en place une navigation à l'aide du SiteMap

Louis-Guillaume MORAND (Traduction)

Apprenez comment tirer avantage des SiteMaps pour décrire la structure de navigation de votre site Web. Dans ce tutoriel, vous allez apprendre comment créer un helper HTML de menu qui génère automatiquement des liens depuis un SiteMap.

- Titre : Comment mettre en place une navigation à l'aide du SiteMap

- Auteur : Louis-Guillaume MORAND (Traduction)

- Parution : 1 mai 2009

- Mise à jour : 1 mai 2009

- Licence : Copyright ® 2009 Equipe dotnet. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Traduction

- Introduction

- Créer un SiteMap

- Comprendre l'API SiteMap

- Créer un helper HTML Menu

- L'importance des URLs canoniques

- Conclusion

- Remerciements

Traduction

Cet article est la traduction la plus fidèle possible de l'article original : Providing Website Navigation with SiteMaps

Introduction

Un SiteMap vous permet de décrire la structure de navigation d'un site Web séparément de la façon dont sont exposées les URLs à travers les contrôleurs et les contrôleurs d'action. Un SiteMap vous permet de décrire comment les pages dans une application Asp.Net MVC sont reliées entre elles, pour un objectif de navigation.
Vous pouvez utiliser un SiteMap, en combinaison avec l'API SiteMap, pour générer les liens de navigation pour votre site Web. Par exemple, vous pouvez utiliser les SiteMaps pour générer menus, onglets, arborescences, liens précédent et suivant ou encore un fil d'Ariane. Dans ce tutoriel, je vais démontrer comment un simple HTML Helper Menu() peut générer automatiquement les liens depuis un SiteMap.

Dans une application Asp.Net Web Forms, vous pouvez utiliser une fonctionnalité des SiteMap nommée "découpage sécurisé", pour n'afficher que les liens de navigation qu'un utilisateur est autorisé à voir. Par exemple, lorsque le découpage sécurisé est activé, vous pouvez cacher le lien Administration pour chaque utilisateur qui n'est pas autorisé à afficher la page Administration. Par défaut, le découpage sécurisé n'est pas supporté avec une application Asp.Net MVC.

Créer un SiteMap

La façon la plus facile de créer un SiteMap est de créer un fichier XML qui décrit la structure de navigation de votre site Web. Vous pouvez créer un nouveau SiteMap dans Visual Studio en sélectionnant le menu Projet > Ajouter un nouvel élément et ajouter un SiteMap (voir Image 1). Pour que votre SiteMap fonctionne avec d'autres configurations, vous devez nommer votre fichier Web.SiteMap et vous devez le placer à la racine de votre application.

Ajout d'un fichier SiteMap

Un fichier XML SiteMap contient un élément racine <siteMap> qui contient un ou plusieurs éléments <siteMapNode> . Vous pouvez placer un élément <siteMapNode> à l'intérieur d'un autre élément <siteMapNode>. Vous utilisez ces éléments <siteMapNode> pour décrire la relation entre les pages dans votre application ASP.Net MVC.

Chaque élément <siteMapNode> peut avoir les attributs suivants (ce n'est pas une liste exhaustive):
- url – L'URL de la page. Utilisée pour créer l'URL d'un lien de navigation,
- title – Le titre de la page,
- description – La description de la page,
- resourceKey – A resource key that you can use to localize the siteMapNode to multiple languages
- siteMapFile – Le chemin vers un autre fichier SiteMap. Utilisé lorsqu'un SiteMap est découpé en plusieurs sous-fichiers.

Les documents XML sont sensibles à la casse, ainsi il y a une différence entre <siteMapNode> et <SiteMapNode>.

Le fichier SiteMap suivant contient quatre éléments <siteMapNode>. Il décrit un site Web qui contient une page d'accueil Home et quatre autres pages titrées Products, Services et About.

Web.sitemap

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode
url="~/"
title="Home"
description="The Home Page">
<siteMapNode
url="~/Product/Index"
title="Products"
description="Our Products" />
<siteMapNode
url="~/Service/Index"
title="Services"
description="Our Services" />
<siteMapNode
url="~/Home/About"
title="About"
description="About Us" />

</siteMapNode>
</siteMap>

Comprendre l'API SiteMap

Vous interagissez avec un SiteMap à travers l'API SiteMap. L'API est représenté par la classe statique SiteMap. Parce que la classe est statique, vous pouvez accédez à cette classe depuis n'importe où dans une application ASP.Net MVC sans rien faire de spécial. (Vous pouvez accéder à la classe directement depuis des contrôleurs, des vues, des helpers, etc.).

La classe statique SiteMap a deux propriétés importantes :
- CurrentNode – Retourne le SiteMapNode qui correspond à la localisation actuelle de l'utilisateur dans le site Web.
- RootNode – Retourne le SiteMapNode racine.

Vous utilisez la classe SiteMap pour déterminer où vous êtes dans un SiteMap. Vous utilisez les propriétés et méthodes de la classe SiteMap pour générer des liens de navigation. Il existe quelques propriétés intéressantes sur cette classe :

- ChildNodes - Retourne tous les enfants SiteMapNodes.

- Description - Retourne la description d'un SiteMapNode.

- NextSibling - Retourne le prochain SiteMapNode de même niveau.

- ParentNode - Retourne le SiteMapNode parent.

- PreviousSibling - Retourne le précédent SiteMapNode de même niveau.

- Title - Retourne le titre d'un SiteMapNode.

- Url - Retourne l'URL d'un SiteMapNode.

Créer un helper HTML Menu

Vous pouvez tirer avantage des SiteMaps et de l'API SiteMap, pour créer des helpers HTML qui générent les liens de navigation. Par exemple, le helper suivant fait exactement cela :

Helpers\MenuHelper.cs

using System.Text;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Helpers
{
public static class MenuHelper
{
public static string Menu(this HtmlHelper helper)
{
var sb = new StringBuilder();

// Create opening unordered list tag
sb.Append("<ul class='menu'>");

// Render each top level node
var topLevelNodes = SiteMap.RootNode.ChildNodes;
foreach (SiteMapNode node in topLevelNodes)
{
if (SiteMap.CurrentNode == node)
sb.AppendLine("<li class='selectedMenuItem'>");
else
sb.AppendLine("<li>");

sb.AppendFormat("<a href='{0}'>{1}</a>", node.Url, helper.Encode(node.Title));
sb.AppendLine("</li>");
}

// Close unordered list tag
sb.Append("</ul>");

return sb.ToString();
}

}
}

Le code contient une méthode d'extension nommée Menu() qui étend la classe HtmlHelper. Cette méthode attrape tous les noeuds enfants du noeud racine et retourne une liste de liens. Les liens sont affichés dans une liste non ordonnée <ul>.
La propriété SiteMap.CurrentNode est utilisée pour déterminer si un lien affiché correspond à la position courante de l'utilisation. Le noeud courant est alors marqué avec la classe CSS selectedMenuItem.
Vous pouvez utiliser le helper HTML Menu() dans une vue particulière. Pourtant, cela a plus de sens d'appeler la méthode Menu() depuis une vue Master Page. De cette façon, le menu apparaitra dans toutes les vues de votre application.

La vue Master Page suivante illustre comment vous pouvez utiliser la méthode Menu().

Site.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Master.cs" Inherits="MvcApplication1.Views.Shared.Site" %>
<%@ Import Namespace="MvcApplication1.Helpers" %>
<!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 runat="server">
<title></title>
<style type="text/css">

.menu
{
list-style:none;
padding:0px;
margin:0px;
}

.menu li
{
float:left;
}

.menu a
{
display:block;
background-color:#eeeeee;
color:Black;
font-weight:bold;
padding:4px;
border:solid 1px black;
text-decoration:none;
margin:2px;
}

.selectedMenuItem a
{
background-color: White;
}

</style>

</head>
<body>
<div>

<%= Html.Menu() %>

<br style="clear:both" />

<asp:ContentPlaceHolder
ID="ContentPlaceHolder1"
runat="server" />

</div>
</body>
</html>

Notez que l'espace de nom MvcApplication1.Helpers est important au niveau de la vue Master Page. Vous devez importer cet espace de nom pour que la méthode d'extension apparaisse en tant que méthode de la propriété HTML.

Notez également que la vue Master Page contient une feuille CSS qui est utilisée pour styliser le menu de navigation rendu par le helper Menu(). Cette feuille CSS est utilisée pour transformer la simple liste en un bandeau d'onglets (voir capture suivante).
Lorsque vous cliquez sur un lien du menu, l'élément sélectionné est surligné avec le style défini par la classe CSS selectedMenuItem CSS. Cette classe précise que l'élément est affiché avec un fond blanc tandis que les autres éléments non sélectionnés auront un fond gris.

Rendu du HTML helper

L'importance des URLs canoniques

Dans une application ASP.Net MVC, plusieurs URLs peuvent être mappés à la même action contrôleur. Par exemple, par défaut, vous pouvez invoquer l'action Index() du contrôleur Home en appelant n'importe laquelle des URLs suivantes :
http://www.MySite.com/
http://www.MySite.com /Home
http://www.MySite.com /Home/Index

Les routes par défaut définies dans le fichier Global.asax mappe ces trois URLs à la même action contrôleur. Plus encore, vous pouvez invoquer l'action Index exposée par le contrôleur Production, en appelant l'une des URLs suivantes :
http://www.MySite.com/Product/
http://www.MySite.com/Product/Index

Cette fonctionnalité du framework ASP.Net MVC peut causer des problèmes lorsque vous utilisez des SiteMaps. Lorsque vous créez un fichier XML SiteMap standard, vous pouvez associer chaque SiteMapNode avec seulement une URL. Dans notre cas, vous ne pouvez associer qu'une seule adresse à l'action Index du contrôleur Home. Les autres adresses pour la même action ne correspondront pas au bon SiteMapNode. Donc, qu'est-ce qu'on peut faire?

Une option est de modifier les routes définies dans le fichier Global.asax pour que plusieurs adresses ne puissent être mappées pour une même action contrôleur. Par exemple, au lieu de définir la route Default comme cela :

routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);

Vous pouvez remplacer la définition de la route Default par les deux définitions de route suivantes :

routes.MapRoute(
"Home",
"",
new { controller = "Home", action = "Index", id = "" }
);

routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { id = "" }
);

La première définition de route mappe l'URL http://www.MySite.com/ sur l'action Index du contrôleur Home. La seconde définition de route mappe une URL telle que http://www.MySite.com/Product/Index sur l'action Index du contrôleur Product.
Les routes modifiées ne correspondront pas à une URL telle que http://www.MySite.com/Home/Index ou http://www.MySite.com/Product. Les routes modifiées ne correspondent qu'à une et une seule URL vers une action contrôleur. En d'autres mots, vous êtes forcés d'utiliser des adresses canoniques pour toutes vos actions contrôleur.

Une autre solution au problème des adresses canoniques est d'utiliser le module d'URL Rewriting de IIS 7.0. Vous pouvez en apprendre plus en lisant l'article suivant : http://learn.iis.net/page.aspx/460/using-url-rewrite-module/

Conclusion

Dans ce tutoriel, vous avez appris comment utiliser des SiteMaps pour décrire la structure de navigation de vos sites Web ASP.Net MVC. Vous avez appris comment créer des nouveaux fichiers XML SiteMap et interagir avec l'API SiteMap. Pour finir, vous avez appris comment créer un helper HTML personnalisé qui génère automatiquement un menu de lien pour le site Web.

Remerciements

Merci à dourou05 pour les corrections apportées à l'article.