Partager via


Création d’un fournisseur de plan de site personnalisé piloté par une base de données (C#)

par Scott Mitchell

Télécharger le PDF

Le fournisseur de mappage de site par défaut dans ASP.NET 2.0 récupère ses données à partir d’un fichier XML statique. Bien que le fournisseur XML soit adapté à de nombreux sites Web de petite taille et de taille moyenne, les applications web plus volumineuses nécessitent une carte de site plus dynamique. Dans ce tutoriel, nous allons créer un fournisseur de cartes de site personnalisé qui récupère ses données à partir de la couche logique métier, qui récupère à son tour les données de la base de données.

Introduction

ASP.NET fonctionnalité de carte de site de la version 2.0 permet à un développeur de pages de définir une carte de site d’application web dans un support persistant, par exemple dans un fichier XML. Une fois définies, les données de carte de site sont accessibles par programmation via la classe dans l’espace System.Web SiteMap de noms ou via divers contrôles web de navigation, tels que les contrôles SiteMapPath, Menu et TreeView. Le système de carte de site utilise le modèle de fournisseur afin que différentes implémentations de sérialisation de carte de site puissent être créées et connectées à une application web. Le fournisseur de cartes de site par défaut fourni avec ASP.NET 2.0 conserve la structure de la carte de site dans un fichier XML. De retour dans le didacticiel De navigation de pages maîtres et de site , nous avons créé un fichier nommé Web.sitemap qui contenait cette structure et avons mis à jour son code XML avec chaque nouvelle section du didacticiel.

Le fournisseur de cartes de site basé sur XML par défaut fonctionne bien si la structure de la carte de site est assez statique, par exemple pour ces didacticiels. Dans de nombreux scénarios, toutefois, une carte de site plus dynamique est nécessaire. Considérez la carte de site affichée dans la figure 1, où chaque catégorie et chaque produit apparaissent sous forme de sections dans la structure du site web. Avec cette carte de site, la visite de la page web correspondant au nœud racine peut répertorier toutes les catégories, tandis que la visite d’une page web de catégorie particulière répertorie les produits de cette catégorie et l’affichage d’une page web de produit spécifique affiche les détails du produit.

Les catégories et produits maquillagent la structure de la carte de site

Figure 1 : Catégories et produits maquillage de la structure de la carte de site (cliquez pour afficher l’image de taille complète)

Bien que cette structure basée sur une catégorie et un produit puisse être codée en dur dans le Web.sitemap fichier, le fichier doit être mis à jour chaque fois qu’une catégorie ou un produit a été ajouté, supprimé ou renommé. Par conséquent, la maintenance de la carte de site serait considérablement simplifiée si sa structure a été récupérée à partir de la base de données ou, dans l’idéal, à partir de la couche logique métier de l’architecture de l’application. Ainsi, à mesure que des produits et des catégories ont été ajoutés, renommés ou supprimés, la carte de site est automatiquement mise à jour pour refléter ces modifications.

Étant donné que la sérialisation de la carte de site de ASP.NET 2.0 est créée en haut du modèle de fournisseur, nous pouvons créer notre propre fournisseur de cartes de site personnalisé qui récupère ses données à partir d’un autre magasin de données, tel que la base de données ou l’architecture. Dans ce tutoriel, nous allons créer un fournisseur personnalisé qui récupère ses données à partir de la BLL. Commençons !

Remarque

Le fournisseur de carte de site personnalisé créé dans ce tutoriel est étroitement couplé à l’architecture et au modèle de données de l’application. Jeff Prosise stocke des cartes de site dans SQL Server et le fournisseur de cartes de site SQL Que vous avez attendu pour examiner une approche généralisée du stockage des données de carte de site dans SQL Server.

Étape 1 : Création des pages web du fournisseur de cartes de site personnalisées

Avant de commencer à créer un fournisseur de carte de site personnalisé, nous allons d’abord ajouter les pages ASP.NET dont nous aurons besoin pour ce didacticiel. Commencez par ajouter un nouveau dossier nommé SiteMapProvider. Ensuite, ajoutez les ASP.NET pages suivantes à ce dossier, en veillant à associer chaque page à la Site.master page maître :

  • Default.aspx
  • ProductsByCategory.aspx
  • ProductDetails.aspx

Ajoutez également un CustomProviders sous-dossier au App_Code dossier.

Ajouter les pages ASP.NET pour les didacticiels relatifs au fournisseur de cartes de site

Figure 2 : Ajouter les pages ASP.NET pour les didacticiels liés au fournisseur de cartes de site

Étant donné qu’il n’existe qu’un seul didacticiel pour cette section, nous n’avons pas besoin Default.aspx de répertorier les didacticiels de la section. Au lieu de cela, Default.aspx affiche les catégories dans un contrôle GridView. Nous aborderons cela à l’étape 2.

Ensuite, mettez à jour Web.sitemap pour inclure une référence à la Default.aspx page. Plus précisément, ajoutez le balisage suivant après la mise en cache <siteMapNode>:

<siteMapNode 
    title="Customizing the Site Map" url="~/SiteMapProvider/Default.aspx" 
    description="Learn how to create a custom provider that retrieves the site map 
                 from the Northwind database." />

Après la mise à jour Web.sitemap, prenez un moment pour afficher le site web des didacticiels via un navigateur. Le menu de gauche inclut désormais un élément pour le seul didacticiel du fournisseur de cartes de site.

La carte de site inclut désormais une entrée pour le didacticiel du fournisseur de cartes de site

Figure 3 : La carte de site inclut désormais une entrée pour le didacticiel du fournisseur de cartes de site

Ce didacticiel se concentre principalement sur la création d’un fournisseur de cartes de site personnalisé et la configuration d’une application web pour utiliser ce fournisseur. En particulier, nous allons créer un fournisseur qui retourne une carte de site qui inclut un nœud racine ainsi qu’un nœud pour chaque catégorie et produit, comme illustré dans la figure 1. En général, chaque nœud de la carte de site peut spécifier une URL. Pour notre carte de site, l’URL du nœud racine sera ~/SiteMapProvider/Default.aspx, qui répertoriera toutes les catégories de la base de données. Chaque nœud de catégorie de la carte de site a une URL qui pointe vers ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID, qui répertorie tous les produits dans le categoryID spécifié. Enfin, chaque nœud de carte de site de produit pointe vers ~/SiteMapProvider/ProductDetails.aspx?ProductID=productID, ce qui affiche les détails spécifiques du produit.

Pour commencer, nous devons créer les pages et ProductDetails.aspx les Default.aspxpagesProductsByCategory.aspx. Ces pages sont effectuées dans les étapes 2, 3 et 4, respectivement. Étant donné que la poussée de ce didacticiel se trouve sur les fournisseurs de cartes de site et que les didacticiels passés ont abordé la création de ces types de rapports maître/détail multipage, nous allons nous dépêcher d’effectuer les étapes 2 à 4. Si vous avez besoin d’un actualiseur lors de la création de rapports maître/détail qui s’étendent sur plusieurs pages, reportez-vous au didacticiel Master/Detail Filtering Sur deux pages .

Étape 2 : Affichage d’une liste de catégories

Ouvrez la Default.aspx page dans le SiteMapProvider dossier et faites glisser un GridView à partir de la boîte à outils sur le Concepteur, en lui affectant la ID Categoriesvaleur . À partir de la balise active GridView, liez-la à un nouvel ObjectDataSource nommé CategoriesDataSource et configurez-la afin qu’elle récupère ses données à l’aide de la méthode s de GetCategories classeCategoriesBLL. Étant donné que ce GridView affiche simplement les catégories et ne fournit pas de fonctionnalités de modification des données, définissez les listes déroulantes dans les onglets UPDATE, INSERT et DELETE sur (None) .

Configurer ObjectDataSource pour retourner des catégories à l’aide de la méthode GetCategories

Figure 4 : Configurer ObjectDataSource pour renvoyer des catégories à l’aide de la GetCategories méthode (Click pour afficher l’image de taille complète)

Définir les listes déroulantes dans les onglets UPDATE, INSERT et DELETE sur (Aucun)

Figure 5 : Définir les listes déroulantes dans les onglets UPDATE, INSERT et DELETE sur (Aucun) (Cliquez pour afficher l’image de taille complète)

Une fois l’Assistant Configuration de la source de données terminée, Visual Studio ajoute un BoundField pour CategoryID, CategoryName, Description, NumberOfProductset BrochurePath. Modifiez GridView de sorte qu’il contient uniquement les CategoryName champs boundFields et Description mettez à jour la CategoryName propriété BoundField sur HeaderText Category.

Ensuite, ajoutez un HyperLinkField et positionnez-le pour qu’il soit le champ le plus à gauche. Définissez la DataNavigateUrlFields propriété sur CategoryID et la DataNavigateUrlFormatString propriété sur ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0}. Définissez la Text propriété sur Afficher les produits .

Ajouter un champ HyperLinkField aux catégories GridView

Figure 6 : Ajouter un HyperLinkField à Categories GridView

Après avoir créé ObjectDataSource et personnalisé les champs GridView, les deux contrôles de balisage déclaratif se présentent comme suit :

<asp:GridView ID="Categories" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="CategoryID" DataSourceID="CategoriesDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:HyperLinkField DataNavigateUrlFields="CategoryID" 
            DataNavigateUrlFormatString=
                "~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0}"
            Text="View Products" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" 
            SortExpression="CategoryName" />
        <asp:BoundField DataField="Description" HeaderText="Description" 
            SortExpression="Description" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories" 
    TypeName="CategoriesBLL"></asp:ObjectDataSource>

La figure 7 montre Default.aspx quand un navigateur est affiché. Si vous cliquez sur un lien ProductsByCategory.aspx?CategoryID=categoryIDAfficher les produits d’une catégorie, nous allons générer à l’étape 3.

Chaque catégorie est répertoriée avec un lien Afficher les produits

Figure 7 : Chaque catégorie est répertoriée avec un lien Afficher les produits (cliquez pour afficher l’image de taille complète)

Étape 3 : Liste des produits de catégorie sélectionnés

Ouvrez la ProductsByCategory.aspx page et ajoutez un GridView, en le ProductsByCategorynommant . À partir de sa balise active, liez GridView à un nouvel ObjectDataSource nommé ProductsByCategoryDataSource. Configurez ObjectDataSource pour utiliser la ProductsBLL méthode de GetProductsByCategoryID(categoryID) classe et définissez les listes déroulantes sur (None) dans les onglets UPDATE, INSERT et DELETE.

Utiliser la méthode GetProductsByCategoryID(categoryID) de la classe ProductsBLL

Figure 8 : Utiliser la ProductsBLL méthode class s GetProductsByCategoryID(categoryID) (Click pour afficher l’image de taille complète)

La dernière étape de l’Assistant Configurer la source de données invite une source de paramètre pour categoryID. Étant donné que ces informations sont transmises par le champ CategoryIDquerystring, sélectionnez QueryString dans la liste déroulante et entrez CategoryID dans la zone de texte QueryStringField, comme illustré dans la figure 9. Cliquez sur Terminer pour terminer l’Assistant.

Utiliser le champ Querystring CategoryID pour le paramètre categoryID

Figure 9 : Utiliser le CategoryID champ Querystring pour le paramètre categoryID (Cliquez pour afficher l’image de taille complète)

Une fois l’Assistant terminé, Visual Studio ajoute boundFields et CheckBoxField correspondants à GridView pour les champs de données de produit. Supprimez tous les éléments, mais les ProductNamechamps UnitPriceSupplierName englobants. Personnalisez ces trois propriétés BoundFields HeaderText pour lire les propriétés Product, Price et Supplier, respectivement. Mettez en forme BoundField UnitPrice en tant que devise.

Ensuite, ajoutez un HyperLinkField et déplacez-le vers la position la plus à gauche. Définissez sa Text propriété sur Afficher les détails, sa DataNavigateUrlFields propriété ProductIDsur et sa DataNavigateUrlFormatString propriété ~/SiteMapProvider/ProductDetails.aspx?ProductID={0}sur .

Ajouter un affichage HyperLinkField qui pointe vers ProductDetails.aspx

Figure 10 : Ajouter un champ HyperLinkField d’affichage qui pointe vers ProductDetails.aspx

Après avoir effectué ces personnalisations, le balisage déclaratif gridView et ObjectDataSource doit ressembler à ce qui suit :

<asp:GridView ID="ProductsByCategory" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ProductsByCategoryDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:HyperLinkField DataNavigateUrlFields="ProductID" 
            DataNavigateUrlFormatString=
                "~/SiteMapProvider/ProductDetails.aspx?ProductID={0}"
            Text="View Details" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
            HeaderText="Price" HtmlEncode="False" 
            SortExpression="UnitPrice" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" 
            ReadOnly="True" SortExpression="SupplierName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsByCategoryDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" 
            QueryStringField="CategoryID" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Revenez à l’affichage Default.aspx via un navigateur, puis cliquez sur le lien Afficher les produits pour les boissons. Cela vous amènera à ProductsByCategory.aspx?CategoryID=1afficher les noms, les prix et les fournisseurs des produits de la base de données Northwind appartenant à la catégorie Boissons (voir la figure 11). N’hésitez pas à améliorer davantage cette page pour inclure un lien pour renvoyer les utilisateurs à la page de liste de catégories (Default.aspx) et un contrôle DetailsView ou FormView qui affiche le nom et la description de la catégorie sélectionnés.

Les noms, les prix et les fournisseurs des boissons sont affichés

Figure 11 : Les noms des boissons, les prix et les fournisseurs sont affichés (cliquez pour afficher l’image pleine taille)

Étape 4 : Affichage des détails d’un produit

La page finale, affiche ProductDetails.aspxles détails des produits sélectionnés. Ouvrez ProductDetails.aspx et faites glisser un DetailsView à partir de la boîte à outils sur le Concepteur. Définissez la propriété DetailsView ID sur ProductInfo et effacez ses Height valeurs et Width valeurs de propriété. À partir de sa balise active, liez DetailsView à un nouvel ObjectDataSource nommé ProductDataSource, configurant ObjectDataSource pour extraire ses données de la méthode de GetProductByProductID(productID) classeProductsBLL. Comme pour les pages web précédentes créées aux étapes 2 et 3, définissez les listes déroulantes dans les onglets UPDATE, INSERT et DELETE sur (Aucun).

Configurer ObjectDataSource pour utiliser la méthode GetProductByProductID(productID)

Figure 12 : Configurer ObjectDataSource pour utiliser la GetProductByProductID(productID) méthode (Click pour afficher l’image de taille complète)

La dernière étape de l’Assistant Configuration de la source de données invite la source du paramètre productID . Étant donné que ces données passent par le champ ProductIDquerystring, définissez la liste déroulante sur QueryString et la zone de texte QueryStringField sur ProductID. Enfin, cliquez sur le bouton Terminer pour terminer l’Assistant.

Configurer le paramètre productID pour extraire sa valeur à partir du champ Querystring ProductID

Figure 13 : Configurer le paramètre productID pour extraire sa valeur à partir du ProductID champ Querystring (cliquez pour afficher l’image de taille complète)

Une fois l’Assistant Configuration de la source de données terminée, Visual Studio crée des BoundFields correspondants et un CheckBoxField dans DetailsView pour les champs de données de produit. Supprimez les ProductIDchamps , SupplierIDet CategoryID BoundFields et configurez les champs restants comme vous le voyez. Après quelques configurations esthétiques, mon balisage déclaratif DetailsView et ObjectDataSource ressemble à ce qui suit :

<asp:DetailsView ID="ProductInfo" runat="server" AutoGenerateRows="False" 
    DataKeyNames="ProductID" DataSourceID="ProductDataSource" 
    EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName" HeaderText="Product" 
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" 
            ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" 
            ReadOnly="True" SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit" HeaderText="Qty/Unit" 
            SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
            HeaderText="Price" HtmlEncode="False" 
            SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="Units In Stock" 
            SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder" HeaderText="Units On Order" 
            SortExpression="UnitsOnOrder" />
        <asp:BoundField DataField="ReorderLevel" HeaderText="Reorder Level" 
            SortExpression="ReorderLevel" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" 
            SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>
<asp:ObjectDataSource ID="ProductDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductByProductID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="productID" 
            QueryStringField="ProductID" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Pour tester cette page, revenez à Default.aspx la catégorie Afficher les produits pour la catégorie Boissons. Dans la liste des produits de boissons, cliquez sur le lien Afficher les détails pour Chai Tea. Cela vous amènera à ProductDetails.aspx?ProductID=1, qui affiche les détails d’un thé Chai (voir la figure 14).

Fournisseur de Chai Tea, Catégorie, Prix et Autres informations s’affichent

Figure 14 : Fournisseur, catégorie, prix et autres informations de Chai Tea est affiché (cliquez pour afficher l’image de taille complète)

Étape 5 : Comprendre les fonctionnements internes d’un fournisseur de cartes de site

La carte de site est représentée dans la mémoire du serveur web sous la forme d’une collection d’instances SiteMapNode qui forment une hiérarchie. Il doit y avoir exactement une racine, tous les nœuds non racines doivent avoir exactement un nœud parent, et tous les nœuds peuvent avoir un nombre arbitraire d’enfants. Chaque SiteMapNode objet représente une section dans la structure du site web ; ces sections ont généralement une page web correspondante. Par conséquent, la classe a des propriétés telles que Title, Urlet Description, qui fournissent des informations pour la section représenteSiteMapNode.SiteMapNode Il existe également une Key propriété qui identifie de manière unique chacun SiteMapNode dans la hiérarchie, ainsi que les propriétés utilisées pour établir cette hiérarchieChildNodes, , ParentNodeNextSibling, PreviousSiblinget ainsi de suite.

La figure 15 montre la structure de la carte de site générale de la figure 1, mais avec les détails de l’implémentation décrits plus en détail.

Chaque SiteMapNode a des propriétés telles que titre, url, clé, et ainsi de suite

Figure 15 : Chacune SiteMapNode a des propriétés telles que Title, Url, Keyet ainsi de suite (cliquez pour afficher l’image de taille complète)

La carte de site est accessible via la classe de l’espace System.Web de noms.SiteMap Cette propriété de RootNode classe retourne l’instance racine SiteMapNode de la carte de site ; CurrentNode retourne la propriété dont Url la SiteMapNode propriété correspond à l’URL de la page actuellement demandée. Cette classe est utilisée en interne par ASP.NET contrôles web de navigation 2.0.

Lorsque les propriétés de la SiteMap classe sont accessibles, elle doit sérialiser la structure de carte de site à partir d’un support persistant en mémoire. Toutefois, la logique de sérialisation de la carte de site n’est pas codée en dur dans la SiteMap classe. Au lieu de cela, au moment de l’exécution, la SiteMap classe détermine le fournisseur de carte de site à utiliser pour la sérialisation. Par défaut, la XmlSiteMapProvider classe est utilisée, qui lit la structure de la carte de site à partir d’un fichier XML correctement mis en forme. Toutefois, avec un peu de travail, nous pouvons créer notre propre fournisseur de carte de site personnalisé.

Tous les fournisseurs de carte de site doivent être dérivés de la SiteMapProvider classe, qui inclut les méthodes et propriétés essentielles nécessaires pour les fournisseurs de carte de site, mais omet de nombreux détails de l’implémentation. Une deuxième classe, étend StaticSiteMapProviderla SiteMapProvider classe et contient une implémentation plus robuste des fonctionnalités nécessaires. En interne, les StaticSiteMapProvider SiteMapNode instances de la carte de site sont stockées en Hashtable interne et fournissent des méthodes telles AddNode(child, parent)que , RemoveNode(siteMapNode), et Clear() qui ajoutent et suppriment SiteMapNode des s à l’intérieur Hashtable. XmlSiteMapProvider est dérivé de StaticSiteMapProvider.

Lors de la création d’un fournisseur de carte de site personnalisé qui s’étend, il existe deux méthodes abstraites StaticSiteMapProviderqui doivent être substituées : BuildSiteMap et GetRootNodeCore. BuildSiteMap, comme son nom l’indique, est responsable du chargement de la structure de la carte de site à partir du stockage persistant et de sa construction en mémoire. GetRootNodeCore retourne le nœud racine dans la carte de site.

Avant qu’une application web puisse utiliser un fournisseur de carte de site, elle doit être inscrite dans la configuration de l’application. Par défaut, la XmlSiteMapProvider classe est inscrite à l’aide du nom AspNetXmlSiteMapProvider. Pour inscrire des fournisseurs de carte de site supplémentaires, ajoutez le balisage suivant à Web.config:

<configuration>
    <system.web>
        ...
        <siteMap defaultProvider="defaultProviderName">
          <providers>
            <add name="name" type="type" />
          </providers>
        </siteMap>
    </system.web>
</configuration>

La valeur de nom attribue un nom lisible par l’homme au fournisseur tandis que le type spécifie le nom de type complet du fournisseur de carte de site. Nous allons explorer des valeurs concrètes pour les valeurs de nom et de type à l’étape 7, après avoir créé notre fournisseur de cartes de site personnalisé.

La classe de fournisseur de carte de site est instanciée la première fois qu’elle est accessible à partir de la SiteMap classe et reste en mémoire pendant toute la durée de vie de l’application web. Étant donné qu’il n’existe qu’une seule instance du fournisseur de carte de site qui peut être appelée à partir de plusieurs visiteurs de site web simultanés, il est impératif que les méthodes du fournisseur soient thread-safe.

Pour des raisons de performances et d’extensibilité, il est important que nous mettons en cache la structure de carte de site en mémoire et renvoyons cette structure mise en cache plutôt que de la recréer chaque fois que la BuildSiteMap méthode est appelée. BuildSiteMap peut être appelé plusieurs fois par demande de page par utilisateur, en fonction des contrôles de navigation utilisés sur la page et de la profondeur de la structure de la carte de site. Dans tous les cas, si nous ne mettons pas en cache la structure de carte de site, BuildSiteMap chaque fois qu’elle est appelée, nous devons récupérer à nouveau les informations de produit et de catégorie de l’architecture (ce qui entraînerait une requête vers la base de données). Comme nous l’avons vu dans les didacticiels de mise en cache précédents, les données mises en cache peuvent devenir obsolètes. Pour lutter contre ce problème, nous pouvons utiliser des expirations basées sur les dépendances de cache SQL ou temporelles.

Remarque

Un fournisseur de cartes de site peut éventuellement remplacer la Initialize méthode. Initialize est appelé lorsque le fournisseur de carte de site est d’abord instancié et passe tous les attributs personnalisés affectés au fournisseur dans Web.config l’élément <add> comme : <add name="name" type="type" customAttribute="value" />. Il est utile si vous souhaitez autoriser un développeur de pages à spécifier différents paramètres liés au fournisseur de carte de site sans avoir à modifier le code du fournisseur. Par exemple, si nous lisons les données de catégorie et de produits directement à partir de la base de données par opposition à l’architecture, nous souhaitons probablement laisser le développeur de pages spécifier la base de données chaîne de connexion au Web.config lieu d’utiliser une valeur codée en dur dans le code du fournisseur. Le fournisseur de carte de site personnalisé que nous allons générer à l’étape 6 ne remplace pas cette Initialize méthode. Pour obtenir un exemple d’utilisation de la méthode, reportez-vous à l’article Initialize Jeff Prosise sur le stockage des cartes de site dans SQL Server.

Étape 6 : Création du fournisseur de carte de site personnalisé

Pour créer un fournisseur de carte de site personnalisé qui génère la carte de site à partir des catégories et des produits de la base de données Northwind, nous devons créer une classe qui s’étend StaticSiteMapProvider. À l’étape 1, je vous ai demandé d’ajouter un CustomProviders dossier dans le App_Code dossier - ajouter une nouvelle classe à ce dossier nommé NorthwindSiteMapProvider. Ajoutez le code suivant à la classe NorthwindSiteMapProvider :

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.Caching;
public class NorthwindSiteMapProvider : StaticSiteMapProvider
{
    private readonly object siteMapLock = new object();
    private SiteMapNode root = null;
    public const string CacheDependencyKey = 
        "NorthwindSiteMapProviderCacheDependency";
    public override SiteMapNode BuildSiteMap()
    {
        // Use a lock to make this method thread-safe
        lock (siteMapLock)
        {
            // First, see if we already have constructed the
            // rootNode. If so, return it...
            if (root != null)
                return root;
            // We need to build the site map!
            
            // Clear out the current site map structure
            base.Clear();
            // Get the categories and products information from the database
            ProductsBLL productsAPI = new ProductsBLL();
            Northwind.ProductsDataTable products = productsAPI.GetProducts();
            // Create the root SiteMapNode
            root = new SiteMapNode(
                this, "root", "~/SiteMapProvider/Default.aspx", "All Categories");
            AddNode(root);
            // Create SiteMapNodes for the categories and products
            foreach (Northwind.ProductsRow product in products)
            {
                // Add a new category SiteMapNode, if needed
                string categoryKey, categoryName;
                bool createUrlForCategoryNode = true;
                if (product.IsCategoryIDNull())
                {
                    categoryKey = "Category:None";
                    categoryName = "None";
                    createUrlForCategoryNode = false;
                }
                else
                {
                    categoryKey = string.Concat("Category:", product.CategoryID);
                    categoryName = product.CategoryName;
                }
                SiteMapNode categoryNode = FindSiteMapNodeFromKey(categoryKey);
                // Add the category SiteMapNode if it does not exist
                if (categoryNode == null)
                {
                    string productsByCategoryUrl = string.Empty;
                    if (createUrlForCategoryNode)
                        productsByCategoryUrl = 
                            "~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=" 
                            + product.CategoryID;
                    categoryNode = new SiteMapNode(
                        this, categoryKey, productsByCategoryUrl, categoryName);
                    AddNode(categoryNode, root);
                }
                // Add the product SiteMapNode
                string productUrl = 
                    "~/SiteMapProvider/ProductDetails.aspx?ProductID=" 
                    + product.ProductID;
                SiteMapNode productNode = new SiteMapNode(
                    this, string.Concat("Product:", product.ProductID), 
                    productUrl, product.ProductName);
                AddNode(productNode, categoryNode);
            }
            
            // Add a "dummy" item to the cache using a SqlCacheDependency
            // on the Products and Categories tables
            System.Web.Caching.SqlCacheDependency productsTableDependency = 
                new System.Web.Caching.SqlCacheDependency("NorthwindDB", "Products");
            System.Web.Caching.SqlCacheDependency categoriesTableDependency = 
                new System.Web.Caching.SqlCacheDependency("NorthwindDB", "Categories");
            // Create an AggregateCacheDependency
            System.Web.Caching.AggregateCacheDependency aggregateDependencies = 
                new System.Web.Caching.AggregateCacheDependency();
            aggregateDependencies.Add(productsTableDependency, categoriesTableDependency);
            // Add the item to the cache specifying a callback function
            HttpRuntime.Cache.Insert(
                CacheDependencyKey, DateTime.Now, aggregateDependencies, 
                Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, 
                CacheItemPriority.Normal, 
                new CacheItemRemovedCallback(OnSiteMapChanged));
            // Finally, return the root node
            return root;
        }
    }
    protected override SiteMapNode GetRootNodeCore()
    {
        return BuildSiteMap();
    }
    protected void OnSiteMapChanged(string key, object value, CacheItemRemovedReason reason)
    {
        lock (siteMapLock)
        {
            if (string.Compare(key, CacheDependencyKey) == 0)
            {
                // Refresh the site map
                root = null;
            }
        }
    }
    public DateTime? CachedDate
    {
        get
        {
            return HttpRuntime.Cache[CacheDependencyKey] as DateTime?;
        }
    }
}

Commençons par explorer cette méthode de BuildSiteMap classe, qui commence par une lock instruction. L’instruction lock permet uniquement à un thread à la fois d’entrer, sérialisant ainsi l’accès à son code et empêchant deux threads simultanés de passer à pas sur les toes des uns des autres.

La variable root au niveau SiteMapNode de la classe est utilisée pour mettre en cache la structure de la carte de site. Lorsque la carte de site est construite pour la première fois, ou pour la première fois après la modification des données sous-jacentes, root sera null et la structure de la carte de site sera construite. Le nœud racine de la carte de site est affecté root pendant le processus de construction afin que la prochaine fois que cette méthode soit appelée, root ne sera nullpas . Par conséquent, tant que root la structure de la carte de site n’est pas null retournée à l’appelant sans avoir à la recréer.

Si la racine est null, la structure de la carte de site est créée à partir des informations de produit et de catégorie. La carte de site est générée en créant les SiteMapNode instances, puis en formant la hiérarchie par le biais d’appels à la StaticSiteMapProvider méthode s de AddNode classe. AddNode effectue la comptabilité interne, en stockant les instances triées SiteMapNode dans un Hashtable. Avant de commencer à construire la hiérarchie, nous commençons par appeler la Clear méthode, ce qui efface les éléments de l’interne Hashtable. Ensuite, la ProductsBLL méthode de GetProducts classe et les résultats ProductsDataTable sont stockés dans des variables locales.

La construction de la carte de site commence par créer le nœud racine et l’affecter à root. La surcharge du SiteMapNode constructeur utilisé ici et tout au long de cette BuildSiteMap opération est transmise les informations suivantes :

  • Référence au fournisseur de cartes de site (this).
  • Le SiteMapNode s Key. Cette valeur requise doit être unique pour chaque SiteMapNode.
  • Le SiteMapNode s Url. Url est facultatif, mais s’il est fourni, chaque SiteMapNode Url valeur doit être unique.
  • S SiteMapNode Title, qui est requis.

L’appel AddNode(root) de méthode ajoute le SiteMapNode root mappage de site en tant que racine. Ensuite, chacun ProductRow d’eux ProductsDataTable est énuméré. S’il existe déjà une SiteMapNode catégorie de produit actuelle, elle est référencée. Sinon, une nouvelle SiteMapNode pour la catégorie est créée et ajoutée en tant qu’enfant de l’appel SiteMapNode``root AddNode(categoryNode, root) de méthode. Une fois le nœud de catégorie SiteMapNode approprié trouvé ou créé, un SiteMapNode est créé pour le produit actuel et ajouté en tant qu’enfant de la catégorie SiteMapNode via AddNode(productNode, categoryNode). Notez que la valeur de la SiteMapNode propriété de Url catégorie est ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID alors que la propriété du Url produit SiteMapNode est affectée ~/SiteMapNode/ProductDetails.aspx?ProductID=productID.

Remarque

Les produits qui ont une valeur de base de données NULL pour leur CategoryID valeur sont regroupés sous une catégorie SiteMapNode dont Title la propriété est définie sur None et dont Url la propriété est définie sur une chaîne vide. J’ai décidé de définir Url une chaîne vide, car la ProductBLL méthode de classe n’a GetProductsByCategory(categoryID) pas actuellement la possibilité de retourner seulement ces produits avec une NULL CategoryID valeur. De plus, je voulais montrer comment les contrôles de navigation restituent un SiteMapNode élément qui n’a pas de valeur pour sa Url propriété. Je vous encourage à étendre ce tutoriel afin que la propriété None SiteMapNode Url pointe vers ProductsByCategory.aspx, mais affiche uniquement les produits avec NULL CategoryID des valeurs.

Après avoir construit la carte de site, un objet arbitraire est ajouté au cache de données à l’aide d’une dépendance de cache SQL sur les tables et Products les Categories tables via un AggregateCacheDependency objet. Nous avons exploré l’utilisation des dépendances de cache SQL dans le didacticiel précédent, à l’aide des dépendances du cache SQL. Toutefois, le fournisseur de carte de site personnalisé utilise une surcharge de la méthode du cache de Insert données que nous avons encore à explorer. Cette surcharge accepte comme paramètre d’entrée final un délégué appelé lorsque l’objet est supprimé du cache. Plus précisément, nous transmettons un nouveau CacheItemRemovedCallback délégué qui pointe vers la OnSiteMapChanged méthode définie plus loin dans la NorthwindSiteMapProvider classe.

Remarque

La représentation en mémoire de la carte de site est mise en cache via la variable rootau niveau de la classe. Étant donné qu’il n’existe qu’une seule instance de la classe de fournisseur de carte de site personnalisée et que cette instance est partagée entre tous les threads de l’application web, cette variable de classe sert de cache. La BuildSiteMap méthode utilise également le cache de données, mais uniquement comme moyen de recevoir une notification lorsque les données de base de données sous-jacentes dans les Categories tables changent Products . Notez que la valeur placée dans le cache de données est uniquement la date et l’heure actuelles. Les données réelles de la carte de site ne sont pas placées dans le cache de données.

La BuildSiteMap méthode se termine en retournant le nœud racine de la carte de site.

Les méthodes restantes sont assez simples. GetRootNodeCore est responsable du retour du nœud racine. Étant donné que BuildSiteMap retourne la racine, GetRootNodeCore retourne BuildSiteMap simplement la valeur de retour de s. La OnSiteMapChanged méthode revient root à null la suppression de l’élément de cache. Avec la valeur de la nullracine définie sur , la prochaine fois BuildSiteMap qu’elle est appelée, la structure de la carte de site sera reconstruite. Enfin, la CachedDate propriété retourne la valeur de date et d’heure stockée dans le cache de données, si une telle valeur existe. Cette propriété peut être utilisée par un développeur de pages pour déterminer quand les données de carte de site ont été mises en cache pour la dernière fois.

Étape 7 : Inscription duNorthwindSiteMapProvider

Pour que notre application web utilise le NorthwindSiteMapProvider fournisseur de carte de site créé à l’étape 6, nous devons l’inscrire dans la <siteMap> section de Web.config. Plus précisément, ajoutez le balisage suivant dans l’élément <system.web> dans Web.config:

<siteMap defaultProvider="AspNetXmlSiteMapProvider">
  <providers>
    <add name="Northwind" type="NorthwindSiteMapProvider" />
  </providers>
</siteMap>

Ce balisage effectue deux opérations : tout d’abord, il indique que le composant intégré AspNetXmlSiteMapProvider est le fournisseur de cartes de site par défaut ; deuxièmement, il inscrit le fournisseur de carte de site personnalisé créé à l’étape 6 avec le nom convivial de Northwind.

Remarque

Pour les fournisseurs de carte de site situés dans le dossier de l’application App_Code , la valeur de l’attribut type est simplement le nom de la classe. Vous pouvez également créer le fournisseur de carte de site personnalisé dans un projet de bibliothèque de classes distinct avec l’assembly compilé placé dans le répertoire de l’application /Bin web. Dans ce cas, la valeur de l’attribut type serait Espace de noms.ClassName, AssemblyName .

Après la mise à jour Web.config, prenez un moment pour afficher n’importe quelle page des didacticiels dans un navigateur. Notez que l’interface de navigation à gauche affiche toujours les sections et les didacticiels définis dans Web.sitemap. Cela est dû au fait que nous avons quitté AspNetXmlSiteMapProvider le fournisseur par défaut. Pour créer un élément d’interface utilisateur de navigation qui utilise le NorthwindSiteMapProvider, nous devons spécifier explicitement que le fournisseur de cartes de site Northwind doit être utilisé. Nous verrons comment procéder à l’étape 8.

Étape 8 : affichage des informations de carte de site à l’aide du fournisseur de carte de site personnalisé

Avec le fournisseur de carte de site personnalisé créé et inscrit dans Web.config, nous sommes prêts à ajouter des contrôles de navigation aux pages et ProductDetails.aspx aux Default.aspxProductsByCategory.aspxpages du SiteMapProvider dossier. Commencez par ouvrir la Default.aspx page et faites glisser une SiteMapPath boîte à outils vers le Concepteur. Le contrôle SiteMapPath se trouve dans la section Navigation de la boîte à outils.

Ajouter un SiteMapPath à Default.aspx

Figure 16 : Ajouter un SiteMapPath à Default.aspx (cliquez pour afficher l’image de taille complète)

Le contrôle SiteMapPath affiche une barre de navigation, indiquant l’emplacement de la page active dans la carte de site. Nous avons ajouté un SiteMapPath en haut de la page maître dans le didacticiel Pages maîtres et Navigation de site .

Prenez un moment pour afficher cette page via un navigateur. Le SiteMapPath ajouté à la figure 16 utilise le fournisseur de cartes de site par défaut, en extrayant ses données à partir de Web.sitemap. Par conséquent, la barre de navigation affiche la personnalisation d’accueil > de la carte de site, tout comme la barre de navigation dans le coin supérieur droit.

La barre de navigation utilise le fournisseur de carte de site par défaut

Figure 17 : La barre de navigation utilise le fournisseur de carte de site par défaut (cliquez pour afficher l’image de taille complète)

Pour que SiteMapPath soit ajouté à la figure 16, utilisez le fournisseur de carte de site personnalisé que nous avons créé à l’étape 6, définissez sa SiteMapProvider propriété sur Northwind, le nom que nous avons affecté à l’élément NorthwindSiteMapProvider in Web.config. Malheureusement, le Concepteur continue d’utiliser le fournisseur de cartes de site par défaut, mais si vous visitez la page via un navigateur après avoir apporté cette modification de propriété, vous verrez que la barre d’accès utilise désormais le fournisseur de carte de site personnalisé.

Capture d’écran montrant comment la barre de navigation affiche le fournisseur de carte de site personnalisé.

Figure 18 : La barre de navigation utilise désormais le fournisseur NorthwindSiteMapProvider de carte de site personnalisé (cliquez pour afficher l’image de taille complète)

Le contrôle SiteMapPath affiche une interface utilisateur plus fonctionnelle dans les pages et ProductDetails.aspx les ProductsByCategory.aspx pages. Ajoutez un SiteMapPath à ces pages, en définissant la SiteMapProvider propriété dans Northwind. Cliquez Default.aspx sur le lien Afficher les produits pour les boissons, puis sur le lien Afficher les détails du thé Chai. Comme le montre la figure 19, la barre de navigation comprend la section de carte de site actuelle (Thé Chai) et ses ancêtres : Boissons et toutes les catégories .

Capture d’écran montrant comment la barre de navigation affiche la section de carte de site actuelle (Chai Tea) et ses ancêtres (Boissons et Toutes les catégories).

Figure 19 : La barre de navigation utilise désormais le fournisseur NorthwindSiteMapProvider de carte de site personnalisé (cliquez pour afficher l’image de taille complète)

D’autres éléments d’interface utilisateur de navigation peuvent être utilisés en plus de SiteMapPath, tels que les contrôles Menu et TreeView. Les Default.aspxpages et ProductDetails.aspx les pages ProductsByCategory.aspxdu téléchargement pour ce didacticiel, par exemple, incluent tous les contrôles menu (voir la figure 20). Consultez les fonctionnalités de navigation de site sophistiquées de ASP.NET 2.0 et la section Utilisation des contrôles de navigation de site de la ASP.NET 2.0 Pour obtenir un aperçu plus approfondi des contrôles de navigation et du système de carte de site dans ASP.NET 2.0.

Le contrôle Menu répertorie chacune des catégories et produits

Figure 20 : Le contrôle de menu répertorie chacune des catégories et produits (cliquez pour afficher l’image de taille complète)

Comme mentionné précédemment dans ce tutoriel, la structure de carte de site est accessible par programmation via la SiteMap classe. Le code suivant retourne la racine SiteMapNode du fournisseur par défaut :

SiteMapNode root = SiteMap.RootNode;

Étant donné que le AspNetXmlSiteMapProvider fournisseur par défaut de notre application est le code ci-dessus retourne le nœud racine défini dans Web.sitemap. Pour référencer un fournisseur de carte de site autre que la valeur par défaut, utilisez la SiteMap propriété de Providers classe comme suit :

SiteMapNode root = SiteMap.Providers["name"].RootNode;

le nom est le nom du fournisseur de carte de site personnalisé (Northwind, pour notre application web).

Pour accéder à un membre spécifique à un fournisseur de carte de site, utilisez-le SiteMap.Providers["name"] pour récupérer l’instance du fournisseur, puis la convertir en type approprié. Par exemple, pour afficher la NorthwindSiteMapProvider propriété s CachedDate dans une page ASP.NET, utilisez le code suivant :

NorthwindSiteMapProvider customProvider = 
    SiteMap.Providers["Northwind"] as NorthwindSiteMapProvider;
if (customProvider != null)
{
    DateTime? lastCachedDate = customProvider.CachedDate;
    if (lastCachedDate != null)
        LabelID.Text = "Site map cached on: " + lastCachedDate.Value.ToString();
    else
        LabelID.Text = "The site map is being reconstructed!";
}

Remarque

Veillez à tester la fonctionnalité de dépendance du cache SQL. Après avoir visité la Default.aspxsection , et ProductsByCategory.aspxProductDetails.aspx les pages, accédez à l’un des didacticiels de la section Édition, Insertion et Suppression, puis modifiez le nom d’une catégorie ou d’un produit. Revenez ensuite à l’une des pages du SiteMapProvider dossier. En supposant que suffisamment de temps est passé pour le mécanisme d’interrogation pour noter la modification de la base de données sous-jacente, la carte de site doit être mise à jour pour afficher le nouveau nom du produit ou de la catégorie.

Résumé

ASP.NET fonctionnalités de carte de site de la version 2.0 comprend une classe, un SiteMap certain nombre de contrôles web de navigation intégrés et un fournisseur de cartes de site par défaut qui s’attend à ce que les informations de carte de site restent conservées dans un fichier XML. Pour utiliser des informations de carte de site à partir d’une autre source, comme à partir d’une base de données, l’architecture de l’application ou un service web distant, nous devons créer un fournisseur de carte de site personnalisé. Cela implique la création d’une classe qui dérive, directement ou indirectement, de la SiteMapProvider classe.

Dans ce tutoriel, nous avons vu comment créer un fournisseur de carte de site personnalisé basé sur la carte de site sur le produit et les informations de catégorie supprimées de l’architecture de l’application. Notre fournisseur a étendu la StaticSiteMapProvider classe et a entraîné la création d’une BuildSiteMap méthode qui a récupéré les données, construit la hiérarchie de carte de site et mis en cache la structure résultante dans une variable de niveau classe. Nous avons utilisé une dépendance de cache SQL avec une fonction de rappel pour invalider la structure mise en cache lorsque les données ou Products sous-jacentes Categories sont modifiées.

Bonne programmation !

Pour aller plus loin

Pour plus d’informations sur les sujets abordés dans ce tutoriel, consultez les ressources suivantes :

À propos de l’auteur

Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. Il peut être accessible à mitchell@4GuysFromRolla.com. ou via son blog, qui peut être trouvé à http://ScottOnWriting.NET.

Merci spécial à

Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Les réviseurs principaux de ce tutoriel étaient Dave Gardner, Zack Jones, Teresa Murphy et Bernadette Leigh. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.