Creazione di un provider personalizzato di mappe di siti basate su database (VB)

di Scott Mitchell

Scarica il PDF

Il provider predefinito della mappa del sito in ASP.NET 2.0 recupera i dati da un file XML statico. Anche se il provider basato su XML è adatto a molti siti Web di piccole e medie dimensioni, le applicazioni Web più grandi richiedono una mappa del sito più dinamica. In questa esercitazione verrà creato un provider di mappe del sito personalizzato che recupera i dati dal livello della logica di business, che a sua volta recupera i dati dal database.

Introduzione

ASP.NET funzionalità della mappa del sito di 2.0 consente a uno sviluppatore di pagine di definire una mappa del sito dell'applicazione Web in un supporto persistente, ad esempio in un file XML. Una volta definiti, è possibile accedere ai dati della mappa del sito a livello di codice tramite la SiteMap classe nello System.Web spazio dei nomi o tramite un'ampia gamma di controlli Web di spostamento, ad esempio i controlli SiteMapPath, Menu e TreeView. Il sistema di mapping del sito usa il modello del provider in modo che diverse implementazioni di serializzazione della mappa del sito possano essere create e collegate a un'applicazione Web. Il provider predefinito della mappa del sito fornito con ASP.NET 2.0 rende persistente la struttura della mappa del sito in un file XML. Tornare all'esercitazione Pagine master e navigazione sito è stato creato un file denominato Web.sitemap che conteneva questa struttura e ne è stato aggiornato il codice XML con ogni nuova sezione dell'esercitazione.

Il provider predefinito della mappa del sito basato su XML funziona correttamente se la struttura della mappa del sito è abbastanza statica, ad esempio per queste esercitazioni. In molti scenari, tuttavia, è necessaria una mappa del sito più dinamica. Si consideri la mappa del sito illustrata nella figura 1, in cui ogni categoria e prodotto vengono visualizzati come sezioni nella struttura del sito Web. Con questa mappa del sito, visitare la pagina Web corrispondente al nodo radice potrebbe elencare tutte le categorie, mentre visitando una determinata pagina Web di una categoria specifica vengono elencati i prodotti della categoria e visualizzando una determinata pagina Web del prodotto, verranno visualizzati i dettagli del prodotto.

Le categorie e i prodotti truccano la struttura della mappa del sito

Figura 1: Categorie e prodotti Trucco struttura della mappa del sito (fare clic per visualizzare l'immagine a dimensione intera)

Anche se questa struttura basata su categoria e prodotto potrebbe essere hardcoded nel Web.sitemap file, il file deve essere aggiornato ogni volta che una categoria o un prodotto è stato aggiunto, rimosso o rinominato. Di conseguenza, la manutenzione della mappa del sito sarebbe notevolmente semplificata se la relativa struttura è stata recuperata dal database o, idealmente, dal livello della logica di business dell'architettura dell'applicazione. In questo modo, man mano che i prodotti e le categorie sono stati aggiunti, rinominati o eliminati, la mappa del sito verrà aggiornata automaticamente per riflettere queste modifiche.

Poiché ASP.NET serializzazione della mappa del sito di 2.0 è stata creata in cima al modello del provider, è possibile creare un provider personalizzato di mappe del sito che afferra i dati da un archivio dati alternativo, ad esempio il database o l'architettura. In questa esercitazione verrà creato un provider personalizzato che recupera i dati dal BLL. Iniziamo!

Nota

Il provider di mappe del sito personalizzato creato in questa esercitazione è strettamente associato all'architettura e al modello di dati dell'applicazione. Jeff Prosise archivia le mappe dei siti in SQL Server e il provider di mappe del sito SQL in attesa di articoli esaminano un approccio generalizzato all'archiviazione dei dati della mappa del sito in SQL Server.

Passaggio 1: Creazione delle pagine Web del provider di mappe del sito personalizzato

Prima di iniziare a creare un provider di mappe del sito personalizzato, aggiungere prima di tutto le pagine ASP.NET necessarie per questa esercitazione. Per iniziare, aggiungere una nuova cartella denominata SiteMapProvider. Aggiungere quindi le pagine di ASP.NET seguenti a tale cartella, assicurandosi di associare ogni pagina alla Site.master pagina master:

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

Aggiungere anche una CustomProviders sottocartella alla App_Code cartella .

Aggiungere le pagine ASP.NET per le esercitazioni sulla mappa del sito Provider-Related

Figura 2: Aggiungere le pagine di ASP.NET per le esercitazioni sulla mappa del sito Provider-Related

Poiché è disponibile una sola esercitazione per questa sezione, non è necessario Default.aspx elencare le esercitazioni della sezione. Verranno invece Default.aspx visualizzate le categorie in un controllo GridView. Questo argomento verrà affrontato nel passaggio 2.

Aggiornare quindi Web.sitemap per includere un riferimento alla Default.aspx pagina. In particolare, aggiungere il markup seguente dopo la memorizzazione nella 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." />

Dopo l'aggiornamento Web.sitemap, dedicare qualche minuto alla visualizzazione del sito Web delle esercitazioni tramite un browser. Il menu a sinistra include ora una voce per l'esercitazione relativa al solo provider di mappe del sito.

La mappa del sito include ora una voce per l'esercitazione sul provider di mappe del sito

Figura 3: La mappa del sito include ora una voce per l'esercitazione sul provider di mappe del sito

Questa esercitazione ha lo scopo principale di illustrare la creazione di un provider di mappe del sito personalizzato e la configurazione di un'applicazione Web per l'uso di tale provider. In particolare, verrà creato un provider che restituisce una mappa del sito che include un nodo radice insieme a un nodo per ogni categoria e prodotto, come illustrato nella figura 1. In generale, ogni nodo nella mappa del sito può specificare un URL. Per la mappa del sito, l'URL del nodo radice sarà ~/SiteMapProvider/Default.aspx, che elenca tutte le categorie nel database. Ogni nodo di categoria nella mappa del sito avrà un URL che punta a ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID, che elenca tutti i prodotti nel categoryID specificato. Infine, ogni nodo della mappa del sito del prodotto punterà a ~/SiteMapProvider/ProductDetails.aspx?ProductID=productID, che visualizzerà i dettagli del prodotto specifico.

Per iniziare, è necessario creare le Default.aspxpagine , ProductsByCategory.aspxe ProductDetails.aspx . Queste pagine vengono completate rispettivamente nei passaggi 2, 3 e 4. Poiché la spinta di questa esercitazione è costituita dai provider di mappe del sito e dal momento che le esercitazioni precedenti hanno illustrato la creazione di questi tipi di report master/dettaglio su più pagine, si affretta nei passaggi da 2 a 4. Se è necessario un aggiornamento per la creazione di report master/dettagli che si estendono su più pagine, fare riferimento all'esercitazione Filtro master/dettagli tra due pagine .

Passaggio 2: Visualizzazione di un elenco di categorie

Aprire la Default.aspx pagina nella SiteMapProvider cartella e trascinare un controllo GridView dalla casella degli strumenti nella Designer, impostandone su IDCategories. Dallo smart tag di GridView associarlo a un nuovo ObjectDataSource denominato CategoriesDataSource e configurarlo in modo che recuperi i dati usando il CategoriesBLL metodo della GetCategories classe . Poiché gridView visualizza solo le categorie e non fornisce funzionalità di modifica dei dati, impostare gli elenchi a discesa nelle schede UPDATE, INSERT e DELETE su (Nessuno).

Configurare ObjectDataSource per restituire categorie usando il metodo GetCategories

Figura 4: Configurare ObjectDataSource per restituire categorie usando il GetCategories metodo (fare clic per visualizzare l'immagine a dimensione intera)

Impostare il Drop-Down Elenchi nelle schede UPDATE, INSERT e DELETE su (Nessuno)

Figura 5: Impostare il Drop-Down Elenchi nelle schede UPDATE, INSERT e DELETE su (Nessuna) (Fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata Configura origine dati, Visual Studio aggiungerà un BoundField per CategoryID, CategoryName, Description, NumberOfProductse BrochurePath. Modificare GridView in modo che contenga CategoryName solo e Description BoundFields e aggiornare la CategoryName proprietà BoundField in HeaderText Category .

Aggiungere quindi un oggetto HyperLinkField e posizionarlo in modo che sia il campo più a sinistra. Impostare la DataNavigateUrlFields proprietà su CategoryID e la DataNavigateUrlFormatString proprietà su ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0}. Impostare la Text proprietà su Visualizza prodotti .

Aggiungere un oggetto HyperLinkField alle categorie GridView

Figura 6: Aggiungere un hyperLinkField a Categories GridView

Dopo aver creato ObjectDataSource e aver personalizzato i campi di GridView, i due controlli markup dichiarativo avranno un aspetto simile al seguente:

<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 figura 7 mostra Default.aspx quando viene visualizzata tramite un browser. Facendo clic sul collegamento Visualizza prodotti di una categoria si passa a ProductsByCategory.aspx?CategoryID=categoryID, che verrà compilato nel passaggio 3.

Ogni categoria è elencata insieme a un collegamento Visualizza prodotti

Figura 7: Ogni categoria è elencata insieme a un collegamento Visualizza prodotti (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 3: Presentazione dei prodotti della categoria selezionata

Aprire la ProductsByCategory.aspx pagina e aggiungere un controllo GridView, denominandolo ProductsByCategory. Dallo smart tag associare GridView a un nuovo ObjectDataSource denominato ProductsByCategoryDataSource. Configurare ObjectDataSource per usare il ProductsBLL metodo della GetProductsByCategoryID(categoryID) classe e impostare gli elenchi a discesa su (Nessuno) nelle schede UPDATE, INSERT e DELETE.

Utilizzare il metodo GetProductsByCategoryID(categoryID) della classe ProductsBLL

Figura 8: Usare il ProductsBLL metodo class s GetProductsByCategoryID(categoryID) (fare clic per visualizzare l'immagine a dimensione intera)

Il passaggio finale della procedura guidata Configura origine dati richiede un'origine parametro per categoryID. Poiché queste informazioni vengono passate tramite il campo CategoryIDquerystring , selezionare QueryString nell'elenco a discesa e immettere CategoryID nella casella di testo QueryStringField, come illustrato nella figura 9. Fare clic su Fine per completare la procedura guidata.

Usare il campo Querystring CategoryID per il parametro categoryID

Figura 9: Usare il CategoryID campo Querystring per il parametro categoryID (fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata, Visual Studio aggiungerà i campi BoundFields e CheckBoxField corrispondenti a GridView per i campi dati del prodotto. Rimuovere tutti gli elementi tranne ProductName, UnitPricee SupplierName BoundFields. Personalizzare queste tre proprietà BoundFields HeaderText per leggere rispettivamente Product, Price e Supplier. Formattare BoundField UnitPrice come valuta.

Aggiungere quindi un HyperLinkField e spostarlo nella posizione più a sinistra. Impostare la Text relativa proprietà su Visualizza dettagli, la relativa DataNavigateUrlFields proprietà su ProductIDe la relativa DataNavigateUrlFormatString proprietà su ~/SiteMapProvider/ProductDetails.aspx?ProductID={0}.

Aggiungere un oggetto HyperLinkField per i dettagli di visualizzazione che punta a ProductDetails.aspx

Figura 10: Aggiungere un oggetto HyperLinkField dettagli visualizzazione a cui punta ProductDetails.aspx

Dopo aver apportato queste personalizzazioni, il markup dichiarativo di GridView e ObjectDataSource dovrebbe essere simile al seguente:

<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>

Tornare alla visualizzazione Default.aspx tramite un browser e fare clic sul collegamento Visualizza prodotti per bevande. Verranno visualizzati ProductsByCategory.aspx?CategoryID=1i nomi, i prezzi e i fornitori dei prodotti nel database Northwind che appartengono alla categoria Bevande (vedere la figura 11). È possibile migliorare ulteriormente questa pagina per includere un collegamento per restituire gli utenti alla pagina dell'elenco di categorie (Default.aspx) e un controllo DetailsView o FormView che visualizza il nome e la descrizione della categoria selezionata.

Vengono visualizzati i nomi delle bevande, i prezzi e i fornitori

Figura 11: Vengono visualizzati i nomi delle bevande, i prezzi e i fornitori (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 4: Visualizzazione dei dettagli di un prodotto

Nella pagina finale, ProductDetails.aspx, vengono visualizzati i dettagli dei prodotti selezionati. Aprire ProductDetails.aspx e trascinare un controllo DetailsView dalla casella degli strumenti nella Designer. Impostare la proprietà DetailsView su ID e cancellarne Height i valori di proprietà e Width .ProductInfo Dallo smart tag associare DetailsView a un nuovo ObjectDataSource denominato ProductDataSource, configurando ObjectDataSource per eseguire il pull dei dati dal ProductsBLL metodo della GetProductByProductID(productID) classe . Come per le pagine Web precedenti create nei passaggi 2 e 3, impostare gli elenchi a discesa nelle schede UPDATE, INSERT e DELETE su (Nessuno).

Configurare ObjectDataSource per l'uso del metodo GetProductByProductID(productID)

Figura 12: Configurare ObjectDataSource per l'uso del metodo (fare clic per visualizzare l'immagineGetProductByProductID(productID) a dimensione intera)

L'ultimo passaggio della procedura guidata Configura origine dati richiede l'origine del parametro productID . Poiché questi dati provengono dal campo ProductIDquerystring , impostare l'elenco a discesa su QueryString e la casella di testo QueryStringField su ProductID. Infine, fare clic sul pulsante Fine per completare la procedura guidata.

Configurare il parametro productID per eseguire il pull del relativo valore dal campo Querystring ProductID

Figura 13: Configurare il parametro productID per eseguire il pull del ProductID valore dal campo Querystring (fare clic per visualizzare l'immagine a dimensione intera)

Dopo aver completato la procedura guidata Configura origine dati, Visual Studio creerà i campi BoundFields corrispondenti e un controllo CheckBoxField in DetailsView per i campi dati del prodotto. ProductIDRimuovere , SupplierIDe CategoryID BoundFields e configurare i campi rimanenti in base alle esigenze. Dopo alcune configurazioni estetiche, il markup dichiarativo detailsView e ObjectDataSource di ObjectDataSource hanno un aspetto simile al seguente:

<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>

Per testare questa pagina, tornare a Default.aspx e fare clic su Visualizza prodotti per la categoria Bevande. Nell'elenco dei prodotti per bevande fare clic sul collegamento Visualizza dettagli per Chai Tea. Verrà visualizzata ProductDetails.aspx?ProductID=1la sezione , che mostra i dettagli di chai tea (vedere la figura 14).

Viene visualizzato Chai Tea s Supplier, Category, Price e Altre informazioni

Figura 14: Viene visualizzato Chai Tea s Supplier, Category, Price e Other Information (Fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 5: Informazioni sui lavori interni di un provider di mappe del sito

La mappa del sito è rappresentata nella memoria del server Web come raccolta di SiteMapNode istanze che formano una gerarchia. Deve essere presente esattamente una radice, tutti i nodi non radice devono avere esattamente un nodo padre e tutti i nodi possono avere un numero arbitrario di elementi figlio. Ogni oggetto rappresenta una sezione della struttura del sito Web. Queste SiteMapNode sezioni in genere hanno una pagina Web corrispondente. Di conseguenza, la SiteMapNode classe ha proprietà come Title, Urle Description, che forniscono informazioni per la sezione rappresentata da SiteMapNode . Esiste anche una Key proprietà che identifica in modo univoco ogni SiteMapNode oggetto nella gerarchia, nonché le proprietà usate per stabilire questa gerarchiaChildNodes, , ParentNodeNextSibling, PreviousSiblinge così via.

La figura 15 mostra la struttura generale della mappa del sito della figura 1, ma con i dettagli di implementazione delineati in dettaglio più fine.

Ogni SiteMapNode ha proprietà come titolo, URL, chiave e così via

Figura 15: Ognuna SiteMapNode ha proprietà come Title, Url, Keye così via (fare clic per visualizzare l'immagine a dimensione intera)

La mappa del sito è accessibile tramite la SiteMap classe nello spazio deiSystem.Web nomi . Questa proprietà della RootNode classe restituisce l'istanza radice SiteMapNode della mappa del sito. CurrentNode Restituisce la SiteMapNode cui Url proprietà corrisponde all'URL della pagina attualmente richiesta. Questa classe viene usata internamente dai controlli Web di spostamento di ASP.NET 2.0.

Quando si accede alle SiteMap proprietà della classe, è necessario serializzare la struttura della mappa del sito da un supporto persistente in memoria. Tuttavia, la logica di serializzazione della mappa del sito non è hardcoded nella SiteMap classe . In fase di esecuzione, invece, la SiteMap classe determina il provider di mapping del sito da usare per la serializzazione. Per impostazione predefinita, viene utilizzata la XmlSiteMapProvider classe , che legge la struttura della mappa del sito da un file XML formattato correttamente. Tuttavia, con un po' di lavoro è possibile creare un provider personalizzato di mappe del sito.

Tutti i provider della mappa del sito devono essere derivati dalla SiteMapProvider classe , che include i metodi e le proprietà essenziali necessari per i provider della mappa del sito, ma omette molti dei dettagli di implementazione. Una seconda classe, StaticSiteMapProvider, estende la SiteMapProvider classe e contiene un'implementazione più affidabile delle funzionalità necessarie. Internamente, archivia StaticSiteMapProvider le SiteMapNode istanze della mappa del sito in un Hashtable oggetto e fornisce metodi come AddNode(child, parent)e RemoveNode(siteMapNode),Clear() che aggiungono e rimuovono SiteMapNode s all'oggetto interno Hashtable. L'oggetto XmlSiteMapProvider è derivato da StaticSiteMapProvider.

Quando si crea un provider di mapping del sito personalizzato che estende StaticSiteMapProvider, è necessario eseguire l'override di due metodi astratti: BuildSiteMap e GetRootNodeCore. BuildSiteMap, come suggerisce il nome, è responsabile del caricamento della struttura della mappa del sito dall'archiviazione permanente e della sua costruzione in memoria. GetRootNodeCore restituisce il nodo radice nella mappa del sito.

Prima che un'applicazione Web possa usare un provider della mappa del sito, deve essere registrata nella configurazione dell'applicazione. Per impostazione predefinita, la XmlSiteMapProvider classe viene registrata usando il nome AspNetXmlSiteMapProvider. Per registrare altri provider della mappa del sito, aggiungere il markup seguente a Web.config:

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

Il valore name assegna un nome leggibile al provider mentre il tipo specifica il nome completo del tipo del provider della mappa del sito. Verranno esaminati i valori concreti per il nome e i valori di tipo nel passaggio 7, dopo aver creato il provider di mappe del sito personalizzato.

Viene creata un'istanza della classe del provider della mappa del sito la prima volta che si accede dalla SiteMap classe e rimane in memoria per la durata dell'applicazione Web. Poiché esiste una sola istanza del provider di mappe del sito che può essere richiamata da più visitatori del sito Web simultanei, è fondamentale che i metodi del provider siano thread-safe.

Per motivi di prestazioni e scalabilità, è importante memorizzare nella cache la struttura della mappa del sito in memoria e restituire questa struttura memorizzata nella cache anziché ricrearla ogni volta che viene richiamato il BuildSiteMap metodo. BuildSiteMap può essere chiamato più volte per ogni richiesta di pagina per utente, a seconda dei controlli di spostamento in uso nella pagina e della profondità della struttura della mappa del sito. In ogni caso, se la struttura della mappa del sito non viene memorizzata nella cache, BuildSiteMap ogni volta che viene richiamata, è necessario recuperare nuovamente le informazioni sul prodotto e sulla categoria dall'architettura , che genererebbe una query sul database. Come illustrato nelle esercitazioni precedenti sulla memorizzazione nella cache, i dati memorizzati nella cache possono diventare obsoleti. Per risolvere questo problema, è possibile usare le scadenze basate su dipendenze della cache SQL o ora.

Nota

Un provider della mappa del sito può facoltativamente eseguire l'override del Initialize metodo . Initialize viene richiamato quando viene creata per la prima volta un'istanza del provider della mappa del sito e viene passato qualsiasi attributo personalizzato assegnato al provider nell'elemento Web.config<add> , ad esempio : <add name="name" type="type" customAttribute="value" />. È utile se si desidera consentire a uno sviluppatore di pagine di specificare varie impostazioni correlate al provider della mappa del sito senza dover modificare il codice del provider. Ad esempio, se si leggevano i dati di categoria e prodotti direttamente dal database anziché tramite l'architettura, è probabile che lo sviluppatore della pagina specifichi il database stringa di connessione Web.config anziché usare un valore hardcoded nel codice del provider. Il provider della mappa del sito personalizzato che verrà compilato nel passaggio 6 non esegue l'override di questo Initialize metodo. Per un esempio dell'uso del metodo , vedere l'articolo InitializeArchiviazione delle mappe dei siti diJeff Prosise in SQL Server.

Passaggio 6: Creazione del provider di mappe del sito personalizzato

Per creare un provider di mappe del sito personalizzato che compila la mappa del sito dalle categorie e dai prodotti nel database Northwind, è necessario creare una classe che estende StaticSiteMapProvider. Nel passaggio 1 ti ho chiesto di aggiungere una CustomProviders cartella nella App_Code cartella - aggiungere una nuova classe a questa cartella denominata NorthwindSiteMapProvider. Aggiungere il codice seguente alla classe NorthwindSiteMapProvider:

Imports System.Web
Imports System.Web.Caching
Public Class NorthwindSiteMapProvider
    Inherits StaticSiteMapProvider
    Private ReadOnly siteMapLock As New Object()
    Private root As SiteMapNode = Nothing
    Public Const CacheDependencyKey As String = "NorthwindSiteMapProviderCacheDependency"
    Public Overrides Function BuildSiteMap() As System.Web.SiteMapNode
        ' Use a lock to make this method thread-safe
        SyncLock siteMapLock
            ' First, see if we already have constructed the
            ' rootNode. If so, return it...
            If root IsNot Nothing Then
                Return root
            End If
            ' We need to build the site map!
            ' Clear out the current site map structure
            MyBase.Clear()
            ' Get the categories and products information from the database
            Dim productsAPI As New ProductsBLL()
            Dim products As Northwind.ProductsDataTable = productsAPI.GetProducts()
            ' Create the root SiteMapNode
            root = New SiteMapNode( _
                Me, "root", "~/SiteMapProvider/Default.aspx", "All Categories")
            AddNode(root)
            ' Create SiteMapNodes for the categories and products
            For Each product As Northwind.ProductsRow In products
                ' Add a new category SiteMapNode, if needed
                Dim categoryKey, categoryName As String
                Dim createUrlForCategoryNode As Boolean = True
                If product.IsCategoryIDNull() Then
                    categoryKey = "Category:None"
                    categoryName = "None"
                    createUrlForCategoryNode = False
                Else
                    categoryKey = String.Concat("Category:", product.CategoryID)
                    categoryName = product.CategoryName
                End If
                Dim categoryNode As SiteMapNode = FindSiteMapNodeFromKey(categoryKey)
                ' Add the category SiteMapNode if it does not exist
                If categoryNode Is Nothing Then
                    Dim productsByCategoryUrl As String = String.Empty
                    If createUrlForCategoryNode Then
                        productsByCategoryUrl = _
                            "~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=" & _
                            product.CategoryID
                    End If
                    categoryNode = New SiteMapNode _
                        (Me, categoryKey, productsByCategoryUrl, categoryName)
                    AddNode(categoryNode, root)
                End If
                ' Add the product SiteMapNode
                Dim productUrl As String = _
                    "~/SiteMapProvider/ProductDetails.aspx?ProductID=" & _
                    product.ProductID
                Dim productNode As New SiteMapNode _
                    (Me, String.Concat("Product:", product.ProductID), _
                    productUrl, product.ProductName)
                AddNode(productNode, categoryNode)
            Next
            ' Add a "dummy" item to the cache using a SqlCacheDependency
            ' on the Products and Categories tables
            Dim productsTableDependency As New _
                System.Web.Caching.SqlCacheDependency("NorthwindDB", "Products")
            Dim categoriesTableDependency As New _
                System.Web.Caching.SqlCacheDependency("NorthwindDB", "Categories")
            ' Create an AggregateCacheDependency
            Dim aggregateDependencies As 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, AddressOf OnSiteMapChanged)
            ' Finally, return the root node
            Return root
        End SyncLock
    End Function
    Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
        Return BuildSiteMap()
    End Function
    Protected Sub OnSiteMapChanged _
    (key As String, value As Object, reason As CacheItemRemovedReason)
        SyncLock siteMapLock
            If String.Compare(key, CacheDependencyKey) = 0 Then
                ' Refresh the site map
                root = Nothing
            End If
        End SyncLock
    End Sub
    Public ReadOnly Property CachedDate() As Nullable(Of DateTime)
        Get
            Dim value As Object = HttpRuntime.Cache(CacheDependencyKey)
            If value Is Nothing OrElse Not TypeOf value Is Nullable(Of DateTime) Then
                Return Nothing
            Else
                Return CType(value, Nullable(Of DateTime))
            End If
        End Get
    End Property
End Class

Iniziamo con l'esplorazione di questo metodo della BuildSiteMap classe, che inizia con un'istruzionelock . L'istruzione lock consente l'immissione di un solo thread alla volta, serializzando così l'accesso al codice e impedendo a due thread simultanei di eseguire l'istruzione uno sull'altro.

La variabile a livello SiteMapNode di classe viene usata per memorizzare root nella cache la struttura della mappa del sito. Quando la mappa del sito viene costruita per la prima volta o per la prima volta dopo la modifica dei dati sottostanti, root sarà Nothing e verrà costruita la struttura della mappa del sito. Il nodo radice della mappa del sito viene assegnato durante root il processo di costruzione in modo che la volta successiva che questo metodo venga chiamato, root non sarà Nothing. Di conseguenza, purché root la struttura della mappa del sito non Nothing venga restituita al chiamante senza doverla ricreare.

Se root è Nothing, la struttura della mappa del sito viene creata dalle informazioni sul prodotto e sulla categoria. La mappa del sito viene compilata creando le SiteMapNode istanze e quindi formando la gerarchia tramite chiamate al StaticSiteMapProvider metodo della AddNode classe . AddNode esegue la contabilità interna, archiviando le istanze diverse SiteMapNode in un oggetto Hashtable. Prima di iniziare a costruire la gerarchia, si inizia chiamando il Clear metodo , che cancella gli elementi dall'oggetto interno Hashtable. Successivamente, il ProductsBLL metodo della GetProducts classe e il risultante ProductsDataTable vengono archiviati nelle variabili locali.

La costruzione della mappa del sito inizia creando il nodo radice e assegnandolo a root. L'overload del SiteMapNode costruttore usato qui e in tutto questo BuildSiteMap viene passato le informazioni seguenti:

  • Riferimento al provider della mappa del sito (Me).
  • Oggetto SiteMapNode .Key Questo valore obbligatorio deve essere univoco per ogni SiteMapNodeoggetto .
  • Oggetto SiteMapNode .Url Url è facoltativo, ma se specificato, ogni SiteMapNodeUrl valore deve essere univoco.
  • Oggetto SiteMapNode , Titleobbligatorio.

La AddNode(root) chiamata al metodo aggiunge alla SiteMapNoderoot mappa del sito come radice. Successivamente, ogni ProductRow oggetto dell'oggetto ProductsDataTable viene enumerato. Se esiste già un SiteMapNode oggetto per la categoria del prodotto corrente, viene fatto riferimento. In caso contrario, viene creato e aggiunto un nuovo SiteMapNode oggetto per la categoria come elemento figlio di SiteMapNode``root tramite la chiamata al AddNode(categoryNode, root) metodo. Dopo aver trovato o creato il nodo della categoria SiteMapNode appropriato, viene creato un SiteMapNode oggetto per il prodotto corrente e aggiunto come elemento figlio della categoria SiteMapNode tramite AddNode(productNode, categoryNode). Si noti che il valore della proprietà della categoria SiteMapNode è ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID mentre alla proprietà del Url prodotto SiteMapNode è assegnato ~/SiteMapNode/ProductDetails.aspx?ProductID=productID.Url

Nota

I prodotti che hanno un valore di database per il relativo vengono NULL raggruppati in una categoria SiteMapNode la cui Title proprietà è impostata su Nessuno e la cui Url proprietà è impostata su una stringa CategoryID vuota. Ho deciso di impostare su Url una stringa vuota perché il ProductBLL metodo della GetProductsByCategory(categoryID) classe attualmente non ha la possibilità di restituire solo quei prodotti con un NULLCategoryID valore. Inoltre, volevo dimostrare in che modo i controlli di navigazione eseguono il rendering di un oggetto SiteMapNode che non dispone di un valore per la relativa Url proprietà. Ti invito a estendere questa esercitazione SiteMapNode in modo che la proprietà Nessuno punti Url a ProductsByCategory.aspx, ma visualizza solo i prodotti con NULLCategoryID valori.

Dopo aver costruito la mappa del sito, un oggetto arbitrario viene aggiunto alla cache dei dati usando una dipendenza della cache SQL dalle Categories tabelle e Products tramite un AggregateCacheDependency oggetto . È stato esaminato l'uso delle dipendenze della cache SQL nell'esercitazione precedente, uso delle dipendenze della cache SQL. Il provider di mapping del sito personalizzato, tuttavia, usa un overload del metodo della Insert cache dei dati ancora da esplorare. Questo overload accetta come parametro di input finale un delegato chiamato quando l'oggetto viene rimosso dalla cache. In particolare, viene passato un nuovo CacheItemRemovedCallback delegato che punta al OnSiteMapChanged metodo definito ulteriormente nella NorthwindSiteMapProvider classe.

Nota

La rappresentazione in memoria della mappa del sito viene memorizzata nella cache tramite la variabile roota livello di classe . Poiché è presente solo un'istanza della classe provider di mapping del sito personalizzata e poiché tale istanza è condivisa tra tutti i thread nell'applicazione Web, questa variabile di classe funge da cache. Il BuildSiteMap metodo usa anche la cache dei dati, ma solo come mezzo per ricevere una notifica quando i dati del database sottostante nelle Categories tabelle o Products cambiano. Si noti che il valore inserito nella cache dei dati è solo la data e l'ora correnti. I dati effettivi della mappa del sito non sono inseriti nella cache dei dati.

Il BuildSiteMap metodo viene completato restituendo il nodo radice della mappa del sito.

I metodi rimanenti sono abbastanza semplici. GetRootNodeCore è responsabile della restituzione del nodo radice. Poiché BuildSiteMap restituisce la radice, GetRootNodeCore restituisce semplicemente BuildSiteMap il valore restituito. Il OnSiteMapChanged metodo viene impostato root nuovamente su Nothing quando l'elemento della cache viene rimosso. Con il set radice impostato di nuovo su Nothing, la prossima volta BuildSiteMap che viene richiamata, la struttura della mappa del sito verrà ricompilata. Infine, la CachedDate proprietà restituisce il valore data e ora archiviato nella cache dei dati, se tale valore esiste. Questa proprietà può essere usata da uno sviluppatore di pagine per determinare quando i dati della mappa del sito sono stati memorizzati nella cache.

Passaggio 7: RegistrazioneNorthwindSiteMapProvider

Per consentire all'applicazione Web di usare il provider di NorthwindSiteMapProvider mappe del sito creato nel passaggio 6, è necessario registrarlo nella <siteMap> sezione di Web.config. In particolare, aggiungere il markup seguente all'interno dell'elemento <system.web> in Web.config:

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

Questo markup esegue due operazioni: prima, indica che il provider predefinito AspNetXmlSiteMapProvider della mappa del sito è il provider di mappe del sito predefinito; secondo, registra il provider di mappe del sito personalizzato creato nel passaggio 6 con il nome descrittivo dell'utente Northwind .

Nota

Per i provider di mappe del sito che si trovano nella cartella dell'applicazione App_Code , il valore dell'attributo type è semplicemente il nome della classe. In alternativa, il provider di mappe del sito personalizzato potrebbe essere stato creato in un progetto di libreria di classi separato con l'assembly compilato inserito nella directory dell'applicazione /Bin Web. In tal caso, il valore dell'attributo sarebbe Spazio deitype nomi.ClassName, AssemblyName .

Dopo l'aggiornamento Web.config, è necessario un momento per visualizzare qualsiasi pagina dalle esercitazioni in un browser. Si noti che l'interfaccia di spostamento a sinistra mostra ancora le sezioni e le esercitazioni definite in Web.sitemap. Questo perché è stato lasciato AspNetXmlSiteMapProvider come provider predefinito. Per creare un elemento dell'interfaccia utente di spostamento che usa NorthwindSiteMapProvider, è necessario specificare in modo esplicito che il provider di mappe del sito Northwind deve essere usato. Verrà illustrato come eseguire questa operazione nel passaggio 8.

Passaggio 8: Visualizzazione delle informazioni sulla mappa del sito usando il provider di mappe del sito personalizzato

Con il provider di mappe del sito personalizzato creato e registrato in Web.config, è possibile aggiungere controlli di spostamento alle Default.aspxpagine , ProductsByCategory.aspxe ProductDetails.aspx nella SiteMapProvider cartella. Iniziare aprendo la Default.aspx pagina e trascinando una SiteMapPath casella degli strumenti nella Designer. Il controllo SiteMapPath si trova nella sezione Navigazione della casella degli strumenti.

Aggiungere un SiteMapPath a Default.aspx

Figura 16: Aggiungere un SiteMapPath a Default.aspx (Fare clic per visualizzare un'immagine full-size)

Il controllo SiteMapPath visualizza un riquadro di navigazione che indica la posizione della pagina corrente all'interno della mappa del sito. È stato aggiunto un SiteMapPath nella parte superiore della pagina master nell'esercitazione Pagine master e Spostamento sito .

Prendere un momento per visualizzare questa pagina tramite un browser. SiteMapPath aggiunto nella figura 16 usa il provider predefinito della mappa del sito, trascinando i dati da Web.sitemap. Pertanto, il panecrumb mostra Home > Personalizzazione della mappa del sito, proprio come il panecrumb nell'angolo in alto a destra.

Il provider di mappe del sito predefinito usa il provider di mappe del sito predefinito

Figura 17: Il panecrumb usa il provider di mappe del sito predefinito (fare clic per visualizzare l'immagine full-size)

Per avere aggiunto SiteMapPath nella figura 16 usare il provider di mappe del sito personalizzato creato nel passaggio 6, impostare la relativaSiteMapProvider proprietà su Northwind, il nome assegnato all'oggetto NorthwindSiteMapProvider in Web.config. Sfortunatamente, la Designer continua a usare il provider predefinito della mappa del sito, ma se si visita la pagina tramite un browser dopo aver apportato questa modifica della proprietà, si noterà che il provider di mappe del sito personalizzato usa ora il provider di mappe del sito personalizzato.

Screenshot che mostra come viene visualizzato il provider di mappe del sito personalizzato.

Figura 18: Il panecrumb usa ora il provider NorthwindSiteMapProvider personalizzato mappa siti (fare clic per visualizzare l'immagine full-size)

Il controllo SiteMapPath visualizza un'interfaccia utente più funzionale nelle ProductsByCategory.aspx pagine e ProductDetails.aspx . Aggiungere un SiteMapPath a queste pagine, impostando la SiteMapProvider proprietà in entrambi su Northwind. Fare Default.aspx clic sul collegamento Visualizza prodotti per bevande e quindi sul collegamento Visualizza dettagli per Chai Tea. Come illustrato nella figura 19, il panecrumb include la sezione della mappa del sito corrente ( Chai Tea ) e i relativi predecessori: Bevande e Tutte le categorie .

Screenshot che mostra come viene visualizzata la sezione mappa del sito corrente (Chai Tea) e i relativi predecessori (Bevande e tutte le categorie).

Figura 19: Il panecrumb usa ora il provider NorthwindSiteMapProvider personalizzato mappa siti (fare clic per visualizzare l'immagine full-size)

È possibile usare altri elementi dell'interfaccia utente di spostamento oltre a SiteMapPath, ad esempio i controlli Menu e TreeView. Le Default.aspxpagine , ProductsByCategory.aspxe ProductDetails.aspx nel download per questa esercitazione, ad esempio, includono tutti i controlli menu (vedere la figura 20). Vedere ASP.NET 2.0 Sofisticate funzionalità di spostamento del sito e la sezione Uso dei controlli di spostamento del sito delle ASP.NET 2.0 per un'analisi più approfondita dei controlli di spostamento e del sistema mappa del sito in ASP.NET 2.0 .

Controllo menu Elenchi Ognuna delle categorie e dei prodotti

Figura 20: Controllo menu Elenchi Ognuna delle categorie e dei prodotti (fare clic per visualizzare l'immagine full-size)

Come accennato in precedenza in questa esercitazione, è possibile accedere alla struttura della mappa del sito a livello di codice tramite la SiteMap classe . Il codice seguente restituisce la radice SiteMapNode del provider predefinito:

Dim root As SiteMapNode = SiteMap.RootNode

Poiché il provider predefinito per l'applicazione AspNetXmlSiteMapProvider , il codice precedente restituirà il nodo radice definito in Web.sitemap. Per fare riferimento a un provider di mappe del sito diverso dal valore predefinito, usare la SiteMap proprietà della Providers classe come segue:

Dim root As SiteMapNode = SiteMap.Providers("name").RootNode

Dove nome è il nome del provider di mappe del sito personalizzato ( Northwind, per l'applicazione Web).

Per accedere a un membro specifico di un provider di mappe del sito, usare SiteMap.Providers["name"] per recuperare l'istanza del provider e quindi eseguirne il cast nel tipo appropriato. Ad esempio, per visualizzare la NorthwindSiteMapProvider proprietà s CachedDate in una pagina ASP.NET, usare il codice seguente:

Dim customProvider As NorthwindSiteMapProvider = _
    TryCast(SiteMap.Providers("Northwind"), NorthwindSiteMapProvider)
If customProvider IsNot Nothing Then
    Dim lastCachedDate As Nullable(Of DateTime) = customProvider.CachedDate
    If lastCachedDate.HasValue Then
        SiteMapLastCachedDate.Text = _
            "Site map cached on: " & lastCachedDate.Value.ToString()
    Else
        SiteMapLastCachedDate.Text = "The site map is being reconstructed!"
    End If
End If

Nota

Assicurarsi di testare la funzionalità di dipendenza della cache SQL. Dopo aver visitato le Default.aspxpagine , eProductsByCategory.aspxProductDetails.aspx, passare a una delle esercitazioni nella sezione Modifica, inserimento ed eliminazione e modificare il nome di una categoria o prodotto. Tornare quindi a una delle pagine nella SiteMapProvider cartella. Supponendo che il tempo sufficiente sia passato per il meccanismo di polling per prendere nota della modifica al database sottostante, la mappa del sito deve essere aggiornata per visualizzare il nuovo prodotto o il nome della categoria.

Riepilogo

ASP.NET le funzionalità della mappa del sito 2.0 includono una classe, un SiteMap numero di controlli Web di spostamento predefiniti e un provider predefinito della mappa del sito che prevede che le informazioni sulla mappa del sito vengano mantenute in modo permanente in un file XML. Per usare le informazioni sulla mappa del sito da un'altra origine, ad esempio da un database, dall'architettura dell'applicazione o da un servizio Web remoto, è necessario creare un provider di mappe siti personalizzato. Ciò comporta la creazione di una classe che deriva, direttamente o indirettamente, dalla SiteMapProvider classe.

In questa esercitazione è stato illustrato come creare un provider di mappe del sito personalizzato che basa la mappa del sito sul prodotto e le informazioni sulle categorie generate dall'architettura dell'applicazione. Il provider ha esteso la StaticSiteMapProvider classe e ha comportato la creazione di un BuildSiteMap metodo che ha recuperato i dati, costruito la gerarchia della mappa del sito e memorizzato nella cache la struttura risultante in una variabile a livello di classe. È stata usata una dipendenza della cache SQL con una funzione di callback per invalidare la struttura memorizzata nella cache quando vengono modificati i dati o Products sottostantiCategories.

Programmazione felice!

Altre informazioni

Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Microsoft Web dal 1998. Scott lavora come consulente indipendente, allenatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2,0 in 24 Ore. Può essere raggiunto a mitchell@4GuysFromRolla.com. o tramite il suo blog, che può essere trovato in http://ScottOnWriting.NET.

Grazie speciali

Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali per questa esercitazione sono stati Dave Gardner, Zack Jones, Teresa Murphy e Bernadette Leigh. Interessati a esaminare i prossimi articoli MSDN? In tal caso, lasciami una riga in mitchell@4GuysFromRolla.com.