Creazione di un provider personalizzato di mappe di siti basate su database (VB)
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.
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 .
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.
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.aspx
pagine , ProductsByCategory.aspx
e 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 ID
Categories
. 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).
Figura 4: Configurare ObjectDataSource per restituire categorie usando il GetCategories
metodo (fare clic per visualizzare l'immagine a dimensione intera)
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
, NumberOfProducts
e 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 .
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.
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.
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 CategoryID
querystring , 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.
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
, UnitPrice
e 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 ProductID
e la relativa DataNavigateUrlFormatString
proprietà su ~/SiteMapProvider/ProductDetails.aspx?ProductID={0}
.
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=1
i 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.
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).
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 ProductID
querystring , 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.
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. ProductID
Rimuovere , SupplierID
e 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=1
la sezione , che mostra i dettagli di chai tea (vedere la figura 14).
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
, Url
e 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
, , ParentNode
NextSibling
, PreviousSibling
e 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.
Figura 15: Ognuna SiteMapNode
ha proprietà come Title
, Url
, Key
e 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 Initialize
Archiviazione 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 ogniSiteMapNode
oggetto . - Oggetto
SiteMapNode
.Url
Url
è facoltativo, ma se specificato, ogniSiteMapNode
Url
valore deve essere univoco. - Oggetto
SiteMapNode
,Title
obbligatorio.
La AddNode(root)
chiamata al metodo aggiunge alla SiteMapNode
root
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 NULL
CategoryID
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 NULL
CategoryID
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 root
a 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.aspx
pagine , ProductsByCategory.aspx
e 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.
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.
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.
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 .
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.aspx
pagine , ProductsByCategory.aspx
e 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 .
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.aspx
pagine , eProductsByCategory.aspx
ProductDetails.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:
- Archiviazione di mappe siti in SQL Server e provider di mappe del sito SQL in attesa
- The Provider Toolkit
- funzionalità di spostamento del sito sofisticate di ASP.NET 2.0
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.
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per