Vytvoření vlastního databázově řízeného zprostředkovatele mapy webu (C#)
Výchozí zprostředkovatel mapy webu v ASP.NET 2.0 načítá data ze statického souboru XML. I když je zprostředkovatel založený na jazyce XML vhodný pro mnoho malých a středně velkých webů, větší webové aplikace vyžadují dynamičtější mapu webu. V tomto kurzu vytvoříme vlastního zprostředkovatele mapy webu, který načítá data z vrstvy obchodní logiky, která pak načítá data z databáze.
Úvod
funkce mapy webu ASP.NET 2.0 umožňuje vývojáři stránek definovat mapu webu webové aplikace v nějakém trvalém médiu, například v souboru XML. Po definování lze k datům mapy webu přistupovat programově prostřednictvím SiteMap
třídy v System.Web
oboru názvů nebo prostřednictvím různých navigačních webových ovládacích prvků, jako jsou SiteMapPath, Menu a TreeView ovládací prvky. Systém map webů používá model zprostředkovatele, aby bylo možné vytvořit a připojit do webové aplikace různé implementace serializace map webů. Výchozí zprostředkovatel mapy webu, který se dodává s ASP.NET 2.0, zachová strukturu mapy webu v souboru XML. Zpět v kurzu Stránky předlohy a Navigace na webu jsme vytvořili soubor s názvem Web.sitemap
, který obsahoval tuto strukturu a aktualizovali jeho XML s každou novou částí kurzu.
Výchozí zprostředkovatel mapování webů založený na jazyce XML funguje dobře, pokud je struktura mapy webu poměrně statická, například pro tyto kurzy. V mnoha scénářích je ale potřeba dynamičtější mapa webu. Představte si mapu webu zobrazenou na obrázku 1, kde se každá kategorie a produkt zobrazují jako oddíly ve struktuře webu. Při použití této mapy webu může návštěva webové stránky odpovídající kořenovému uzlu vypsat všechny kategorie, zatímco při návštěvě webové stránky konkrétní kategorie by se zobrazil seznam produktů dané kategorie a zobrazením webové stránky konkrétního produktu by se zobrazily podrobnosti o produktu.
Obrázek 1: Kategorie a produkty– struktura mapy webu (kliknutím zobrazíte obrázek v plné velikosti)
I když by tato struktura založená na kategoriích a produktech mohla být pevně zakódovaná do Web.sitemap
souboru, je potřeba soubor aktualizovat při každém přidání, odebrání nebo přejmenování kategorie nebo produktu. V důsledku toho by byla údržba mapy webu značně zjednodušena, pokud by její struktura byla načtena z databáze nebo v ideálním případě z vrstvy obchodní logiky architektury aplikace. Při přidání, přejmenování nebo odstranění produktů a kategorií se pak mapa webu automaticky aktualizuje tak, aby odrážela tyto změny.
Vzhledem k tomu, že serializace mapy webu ASP.NET 2.0 je postavena na základě modelu zprostředkovatele, můžeme vytvořit vlastního zprostředkovatele mapy webu, který vezme data z alternativního úložiště dat, jako je databáze nebo architektura. V tomto kurzu sestavíme vlastního zprostředkovatele, který načítá data z BLL. Pusťme se do toho!
Poznámka
Vlastní zprostředkovatel map webů vytvořený v tomto kurzu je úzce svázán s architekturou a datovým modelem aplikace. Jeff Prosise: Ukládání map webů v SQL Server a Zprostředkovatel map webů SQL, na které jste čekali, se zkoumají zobecněný přístup k ukládání dat mapy webu v SQL Server.
Krok 1: Vytvoření vlastních webových stránek zprostředkovatele map webů
Než začneme vytvářet vlastního zprostředkovatele map webů, pojďme nejdřív přidat ASP.NET stránky, které budeme pro účely tohoto kurzu potřebovat. Začněte přidáním nové složky s názvem SiteMapProvider
. Dále do této složky přidejte následující ASP.NET stránky a nezapomeňte každou stránku přidružit ke Site.master
stránce předlohy:
Default.aspx
ProductsByCategory.aspx
ProductDetails.aspx
Do složky také přidejte CustomProviders
podsložku App_Code
.
Obrázek 2: Přidání ASP.NET stránek pro kurzy map Provider-Related webu
Vzhledem k tomu, že pro tuto část existuje pouze jeden kurz, nemusíme Default.aspx
vypisovat kurzy oddílů. Default.aspx
Místo toho zobrazí kategorie v GridView ovládací prvek. Budeme se tím zabývat v kroku 2.
Dále aktualizujte Web.sitemap
tak, aby obsahovala odkaz na Default.aspx
stránku. Konkrétně přidejte následující kód za ukládání do mezipaměti <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." />
Po aktualizaci Web.sitemap
se chvíli podívejte na web kurzů prostřednictvím prohlížeče. Nabídka na levé straně teď obsahuje položku pro kurz o jediném poskytovateli map webů.
Obrázek 3: Mapa webu teď obsahuje položku pro kurz ke zprostředkovateli map webů
Tento kurz se zaměřuje hlavně na ilustraci vytvoření vlastního zprostředkovatele mapy webu a konfigurace webové aplikace pro použití tohoto zprostředkovatele. Konkrétně vytvoříme zprostředkovatele, který vrátí mapu webu, která obsahuje kořenový uzel spolu s uzlem pro každou kategorii a produkt, jak je znázorněno na obrázku 1. Obecně platí, že každý uzel v mapě webu může zadat adresu URL. V mapě webu bude ~/SiteMapProvider/Default.aspx
adresa URL kořenového uzlu , která zobrazí seznam všech kategorií v databázi. Každý uzel kategorie v mapě webu bude mít adresu URL odkazující na ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID
, která zobrazí seznam všech produktů v zadaném id kategorie. Nakonec bude každý uzel mapy webu produktu odkazovat na ~/SiteMapProvider/ProductDetails.aspx?ProductID=productID
, který zobrazí podrobnosti o konkrétním produktu.
Abychom mohli začít, musíme vytvořit Default.aspx
stránky , ProductsByCategory.aspx
a ProductDetails.aspx
. Tyto stránky se dokončí v krocích 2, 3 a 4. Vzhledem k tomu, že podstata tohoto kurzu je na poskytovatelích map webů a vzhledem k tomu, že předchozí kurzy se zabývaly vytvářením těchto typů vícestránkových řídicích/podrobných sestav, pospíšíme si kroky 2 až 4. Pokud si potřebujete zopakovat vytváření hlavních nebo podrobných sestav, které pokrývají více stránek, projděte si kurz Filtrování předlohy/podrobností na dvou stránkách .
Krok 2: Zobrazení seznamu kategorií
Default.aspx
Otevřete stránku ve SiteMapProvider
složce a přetáhněte objekt GridView z panelu nástrojů na Designer s nastavením ID
na Categories
. Z inteligentní značky GridView vytvořte vazbu na nový ObjectDataSource s názvem CategoriesDataSource
a nakonfigurujte ji tak, aby načítala data pomocí CategoriesBLL
metody třídy s GetCategories
. Vzhledem k tomu, že tento objekt GridView pouze zobrazuje kategorie a neposkytuje možnosti úprav dat, nastavte rozevírací seznamy na kartách UPDATE, INSERT a DELETE na (None) .
Obrázek 4: Konfigurace objektu ObjectDataSource tak, aby vracel kategorie pomocí GetCategories
metody (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 5: Nastavte Drop-Down Seznamy na kartách UPDATE (UPDATE), INSERT a DELETE (Žádný) (Kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce Konfigurací zdroje dat přidá Visual Studio BoundField pro CategoryID
, CategoryName
, Description
, NumberOfProducts
a BrochurePath
. Upravte Objekt GridView tak, aby obsahoval CategoryName
pouze a Description
BoundFields, a aktualizujte CategoryName
vlastnost BoundField s HeaderText
na Category .
Dále přidejte pole HyperLinkField a umístěte ho tak, aby se jedná o pole nejvíce vlevo. Vlastnost nastavte DataNavigateUrlFields
na CategoryID
a vlastnost DataNavigateUrlFormatString
na ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0}
. Vlastnost nastavte Text
na View Products (Zobrazit produkty).
Obrázek 6: Přidání HyperLinkField do objektu Categories
GridView
Po vytvoření ObjectDataSource a přizpůsobení polí GridView s budou deklarativní značky dvou ovládacích prvků vypadat takto:
<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>
Obrázek 7 ukazuje Default.aspx
zobrazení v prohlížeči. Kliknutím na odkaz na kategorii Zobrazit produkty přejdete na ProductsByCategory.aspx?CategoryID=categoryID
, který vytvoříme v kroku 3.
Obrázek 7: Každá kategorie je uvedená společně s odkazem Zobrazit produkty (kliknutím zobrazíte obrázek v plné velikosti)
Krok 3: Výpis vybraných produktů kategorie
ProductsByCategory.aspx
Otevřete stránku a přidejte Objekt GridView s pojmenováním ProductsByCategory
. Ze své inteligentní značky vytvořte vazbu objektu GridView na nový objekt ObjectDataSource s názvem ProductsByCategoryDataSource
. Nakonfigurujte ObjectDataSource tak, aby používal metodu ProductsBLL
třídy s GetProductsByCategoryID(categoryID)
, a nastavte rozevírací seznamy na (None) na kartách UPDATE, INSERT a DELETE.
Obrázek 8: Použití ProductsBLL
metody Třídy GetProductsByCategoryID(categoryID)
s (kliknutím zobrazíte obrázek v plné velikosti)
V posledním kroku průvodce Konfigurovat zdroj dat se zobrazí výzva k zadání zdroje parametrů pro categoryID. Vzhledem k tomu, že se tyto informace předávají přes pole CategoryID
řetězce dotazu, vyberte v rozevíracím seznamu Řetězec dotazu a do textového pole QueryStringField zadejte CategoryID, jak je znázorněno na obrázku 9. Dokončete průvodce kliknutím na Dokončit.
Obrázek 9: Použití CategoryID
pole řetězce dotazu pro parametr categoryID (kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce visual Studio přidá odpovídající BoundFields a CheckBoxField do GridView pro pole dat produktu. Odeberte všechna pole kromě ProductName
, UnitPrice
a SupplierName
BoundField. Přizpůsobte tyto tři vlastnosti BoundFields tak, aby četly HeaderText
informace o produktu, ceně a dodavateli v uvedeném pořadí. Naformátujte UnitPrice
BoundField jako měnu.
Dále přidejte Pole HyperLinkField a přesuňte ho na pozici úplně vlevo. Nastavte jeho Text
vlastnost na View Details (Zobrazit podrobnosti), nastavte vlastnost DataNavigateUrlFields
na ProductID
a nastavte vlastnost DataNavigateUrlFormatString
na ~/SiteMapProvider/ProductDetails.aspx?ProductID={0}
.
Obrázek 10: Přidání pole HyperLinkField podrobností zobrazení, které odkazuje na ProductDetails.aspx
Po provedení těchto přizpůsobení by deklarativní značky GridView a ObjectDataSource měly vypadat takto:
<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>
Vraťte se do zobrazení Default.aspx
v prohlížeči a klikněte na odkaz Zobrazit produkty pro nápoje. Tím přejdete na ProductsByCategory.aspx?CategoryID=1
, kde se zobrazí názvy, ceny a dodavatelé produktů v databázi Northwind, které patří do kategorie Nápoje (viz Obrázek 11). Tuto stránku můžete dále vylepšit tak, aby obsahovala odkaz pro návrat uživatelů na stránku se seznamem kategorií (Default.aspx
) a ovládací prvek DetailsView nebo FormView, který zobrazuje název a popis vybrané kategorie.
Obrázek 11: Zobrazí se názvy nápojů, ceny a dodavatelé (kliknutím zobrazíte obrázek v plné velikosti).
Krok 4: Zobrazení podrobností o produktu
Na poslední stránce se ProductDetails.aspx
zobrazí podrobnosti o vybraných produktech. Otevřete ProductDetails.aspx
a přetáhněte zobrazení DetailsView z panelu nástrojů do Designer. Nastavte vlastnost DetailsView s ID
na ProductInfo
a vymažte její Height
hodnoty a Width
vlastnosti. Ze své inteligentní značky vytvořte vazbu DetailsView na nový ObjectDataSource s názvem ProductDataSource
a nakonfigurujte ObjectDataSource tak, aby načítá data z ProductsBLL
metody třídy s GetProductByProductID(productID)
. Stejně jako u předchozích webových stránek vytvořených v krocích 2 a 3 nastavte rozevírací seznamy na kartách UPDATE, INSERT a DELETE na (Žádné) .
Obrázek 12: Konfigurace objektu ObjectDataSource pro použití GetProductByProductID(productID)
metody (kliknutím zobrazíte obrázek v plné velikosti)
V posledním kroku průvodce Konfigurací zdroje dat se zobrazí výzva k zadání zdroje parametru productID . Vzhledem k tomu, že tato data přicházejí přes pole ProductID
řetězce dotazu, nastavte rozevírací seznam na QueryString a textové pole QueryStringField na Idproduktu. Nakonec průvodce dokončete kliknutím na tlačítko Dokončit.
Obrázek 13: Konfigurace parametru productID pro načtení hodnoty z ProductID
pole Řetězce dotazu (kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce Konfigurovat zdroj dat vytvoří Visual Studio odpovídající BoundFields a CheckBoxField v zobrazení DetailsView pro pole s daty produktu. Odeberte pole ProductID
, SupplierID
a CategoryID
BoundFields a podle potřeby nakonfigurujte zbývající pole. Po několika estetických konfiguracích moje deklarativní značky DetailsView a ObjectDataSource vypadaly takto:
<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>
Pokud chcete tuto stránku otestovat, vraťte se na Default.aspx
stránku a klikněte na Zobrazit produkty v kategorii Nápoje. V seznamu nápojových produktů klikněte na odkaz Zobrazit podrobnosti pro Čaj Chai. Tím přejdete na ProductDetails.aspx?ProductID=1
, který zobrazuje podrobnosti o čaji Chai (viz obrázek 14).
Obrázek 14: Zobrazí se informace o dodavateli, kategorii, ceně a dalších informacích (kliknutím zobrazíte obrázek v plné velikosti)
Krok 5: Pochopení vnitřního fungování poskytovatele mapy webu
Mapa webu je v paměti webového serveru reprezentována jako kolekce SiteMapNode
instancí, které tvoří hierarchii. Musí existovat přesně jeden kořenový uzel, všechny jiné než kořenové uzly musí mít přesně jeden nadřazený uzel a všechny uzly můžou mít libovolný počet podřízených uzlů. Každý SiteMapNode
objekt představuje oddíl ve struktuře webu. Tyto oddíly mají obvykle odpovídající webovou stránku. V důsledku toho má třída vlastnosti jako Title
, Url
a Description
, které poskytují informace pro oddíl, který SiteMapNode
představuje.SiteMapNode
Existuje také Key
vlastnost, která jedinečně identifikuje každou SiteMapNode
z těchto hierarchií, a také vlastnosti použité k vytvoření této hierarchie ChildNodes
, ParentNode
, NextSibling
, PreviousSibling
atd.
Obrázek 15 znázorňuje obecnou strukturu mapy webu z obrázku 1, ale s podrobnějšími podrobnostmi o implementaci.
Obrázek 15: Každý z nich SiteMapNode
má vlastnosti, jako jsou Title
, Url
Key
, a tak dále (kliknutím zobrazíte obrázek v plné velikosti)
Mapa webu je přístupná prostřednictvím SiteMap
třídy v System.Web
oboru názvů. Tato vlastnost třídy RootNode
s vrátí kořenovou SiteMapNode
instanci mapy webu. CurrentNode
Vrátí SiteMapNode
vlastnost, jejíž Url
vlastnost odpovídá adrese URL aktuálně požadované stránky. Tuto třídu interně používají ASP.NET 2.0 s navigační webové ovládací prvky.
Při přístupu k SiteMap
vlastnostem třídy s musí serializovat strukturu mapy webu z nějakého trvalého média do paměti. Logika serializace mapy webu však není pevně zakódována do SiteMap
třídy. Místo toho za běhu SiteMap
třída určuje, který zprostředkovatele mapy webu se má použít pro serializaci. Ve výchozím nastavení XmlSiteMapProvider
se používá třída, která čte strukturu mapy webu ze správně naformátovaného souboru XML. S trochou práce ale můžeme vytvořit vlastního poskytovatele map webů.
Všichni zprostředkovatelé mapy webu musí být odvozeni od SiteMapProvider
třídy, která zahrnuje základní metody a vlastnosti potřebné pro zprostředkovatele mapy webu, ale vynechá mnoho podrobností o implementaci. Druhá třída, StaticSiteMapProvider
, rozšiřuje SiteMapProvider
třídu a obsahuje robustnější implementaci potřebných funkcí. Interně StaticSiteMapProvider
ukládá SiteMapNode
instance mapy webu v objektu Hashtable
a poskytuje metody, jako je AddNode(child, parent)
, RemoveNode(siteMapNode),
a Clear()
které přidávají a odebíraly SiteMapNode
objekty s do interního Hashtable
objektu . XmlSiteMapProvider
je odvozeno od StaticSiteMapProvider
.
Při vytváření vlastního zprostředkovatele mapy webu, který rozšiřuje StaticSiteMapProvider
, je potřeba přepsat dvě abstraktní metody: BuildSiteMap
a GetRootNodeCore
. BuildSiteMap
, jak název napovídá, zodpovídá za načtení struktury mapy webu z trvalého úložiště a její vytvoření v paměti. GetRootNodeCore
vrátí kořenový uzel v mapě webu.
Aby webová aplikace mohl používat zprostředkovatele mapy webu, musí být zaregistrovaná v konfiguraci aplikace. Ve výchozím nastavení XmlSiteMapProvider
je třída registrována pomocí názvu AspNetXmlSiteMapProvider
. Pokud chcete zaregistrovat další zprostředkovatele mapy webu, přidejte následující kód do Web.config
:
<configuration>
<system.web>
...
<siteMap defaultProvider="defaultProviderName">
<providers>
<add name="name" type="type" />
</providers>
</siteMap>
</system.web>
</configuration>
Hodnota názvu přiřadí zprostředkovateli název čitelný pro člověka, zatímco typ určuje plně kvalifikovaný název typu poskytovatele mapy webu. Po vytvoření vlastního poskytovatele mapy webu prozkoumáme konkrétní hodnoty názvů a typů v kroku 7.
Třída zprostředkovatele mapy webu se vytvoří při prvním přístupu z SiteMap
třídy a zůstane v paměti po celou dobu životnosti webové aplikace. Vzhledem k tomu, že existuje pouze jedna instance zprostředkovatele mapy webu, která může být vyvolána z více souběžných návštěvníků webu, je nezbytné, aby metody zprostředkovatele byly bezpečné pro přístup z více vláken.
Z důvodů výkonu a škálovatelnosti je důležité ukládat strukturu mapy webu v paměti do mezipaměti a vracet tuto strukturu v mezipaměti, nikoli ji znovu vytvořit při BuildSiteMap
každém vyvolání metody. BuildSiteMap
v závislosti na navigačních ovládacích prvcích, které se používají na stránce a na hloubce struktury mapy webu, může být volána několikrát na jednu stránku. V každém případě, pokud neulovíme strukturu mapy webu do BuildSiteMap
mezipaměti, pak pokaždé, když je vyvolána, budeme muset znovu načíst informace o produktu a kategorii z architektury (což by vedlo k dotazu do databáze). Jak jsme probrali v předchozích kurzech ukládání do mezipaměti, data uložená v mezipaměti můžou být zastaralá. V boji proti tomu můžeme použít vypršení platnosti založených na časových závislostech nebo na mezipamětí SQL.
Poznámka
Zprostředkovatel mapy webu může volitelně přepsat metoduInitialize
. Initialize
se vyvolá při prvním vytvoření instance zprostředkovatele mapy webu a předají se mu všechny vlastní atributy přiřazené zprostředkovateli v Web.config
elementu <add>
, například : <add name="name" type="type" customAttribute="value" />
. Je to užitečné, pokud chcete vývojáři stránky povolit, aby zadal různá nastavení související se zprostředkovatele mapy webu, aniž by bylo nutné upravovat kód zprostředkovatele. Pokud bychom například načítali data kategorií a produktů přímo z databáze, a ne prostřednictvím architektury, pravděpodobně bychom chtěli, aby vývojář stránky zadal databázi připojovací řetězec a Web.config
nepoužívali pevně zakódovanou hodnotu v kódu zprostředkovatele. Vlastní zprostředkovatel mapy webu, který vytvoříme v kroku 6, tuto Initialize
metodu nepřepíše. Příklad použití Initialize
metody najdete v článku o ukládání map webu Jeffa Prosisehov SQL Server článku.
Krok 6: Vytvoření vlastního zprostředkovatele mapy webu
Pokud chcete vytvořit vlastního zprostředkovatele mapy webu, který sestaví mapu webu z kategorií a produktů v databázi Northwind, musíme vytvořit třídu, která rozšiřuje StaticSiteMapProvider
. V kroku 1 jsem vás požádal o CustomProviders
přidání složky do App_Code
složky – přidání nové třídy do této složky s názvem NorthwindSiteMapProvider
. Do třídy přidejte následující kód NorthwindSiteMapProvider
:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.Caching;
public class NorthwindSiteMapProvider : StaticSiteMapProvider
{
private readonly object siteMapLock = new object();
private SiteMapNode root = null;
public const string CacheDependencyKey =
"NorthwindSiteMapProviderCacheDependency";
public override SiteMapNode BuildSiteMap()
{
// Use a lock to make this method thread-safe
lock (siteMapLock)
{
// First, see if we already have constructed the
// rootNode. If so, return it...
if (root != null)
return root;
// We need to build the site map!
// Clear out the current site map structure
base.Clear();
// Get the categories and products information from the database
ProductsBLL productsAPI = new ProductsBLL();
Northwind.ProductsDataTable products = productsAPI.GetProducts();
// Create the root SiteMapNode
root = new SiteMapNode(
this, "root", "~/SiteMapProvider/Default.aspx", "All Categories");
AddNode(root);
// Create SiteMapNodes for the categories and products
foreach (Northwind.ProductsRow product in products)
{
// Add a new category SiteMapNode, if needed
string categoryKey, categoryName;
bool createUrlForCategoryNode = true;
if (product.IsCategoryIDNull())
{
categoryKey = "Category:None";
categoryName = "None";
createUrlForCategoryNode = false;
}
else
{
categoryKey = string.Concat("Category:", product.CategoryID);
categoryName = product.CategoryName;
}
SiteMapNode categoryNode = FindSiteMapNodeFromKey(categoryKey);
// Add the category SiteMapNode if it does not exist
if (categoryNode == null)
{
string productsByCategoryUrl = string.Empty;
if (createUrlForCategoryNode)
productsByCategoryUrl =
"~/SiteMapProvider/ProductsByCategory.aspx?CategoryID="
+ product.CategoryID;
categoryNode = new SiteMapNode(
this, categoryKey, productsByCategoryUrl, categoryName);
AddNode(categoryNode, root);
}
// Add the product SiteMapNode
string productUrl =
"~/SiteMapProvider/ProductDetails.aspx?ProductID="
+ product.ProductID;
SiteMapNode productNode = new SiteMapNode(
this, string.Concat("Product:", product.ProductID),
productUrl, product.ProductName);
AddNode(productNode, categoryNode);
}
// Add a "dummy" item to the cache using a SqlCacheDependency
// on the Products and Categories tables
System.Web.Caching.SqlCacheDependency productsTableDependency =
new System.Web.Caching.SqlCacheDependency("NorthwindDB", "Products");
System.Web.Caching.SqlCacheDependency categoriesTableDependency =
new System.Web.Caching.SqlCacheDependency("NorthwindDB", "Categories");
// Create an AggregateCacheDependency
System.Web.Caching.AggregateCacheDependency aggregateDependencies =
new System.Web.Caching.AggregateCacheDependency();
aggregateDependencies.Add(productsTableDependency, categoriesTableDependency);
// Add the item to the cache specifying a callback function
HttpRuntime.Cache.Insert(
CacheDependencyKey, DateTime.Now, aggregateDependencies,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.Normal,
new CacheItemRemovedCallback(OnSiteMapChanged));
// Finally, return the root node
return root;
}
}
protected override SiteMapNode GetRootNodeCore()
{
return BuildSiteMap();
}
protected void OnSiteMapChanged(string key, object value, CacheItemRemovedReason reason)
{
lock (siteMapLock)
{
if (string.Compare(key, CacheDependencyKey) == 0)
{
// Refresh the site map
root = null;
}
}
}
public DateTime? CachedDate
{
get
{
return HttpRuntime.Cache[CacheDependencyKey] as DateTime?;
}
}
}
Začněme prozkoumáním této metody třídy sBuildSiteMap
, která začíná příkazemlock
. Příkaz lock
umožňuje zadat pouze jedno vlákno najednou, čímž serializuje přístup ke svému kódu a brání dvěma souběžným vláknům v krokování na sebe s prsty.
Proměnná root
na úrovni SiteMapNode
třídy se používá k ukládání struktury mapy webu do mezipaměti. Při prvním vytvoření mapy webu nebo poprvé po úpravě root
null
podkladových dat se vytvoří struktura mapy webu. Kořenový uzel mapy webu je přiřazen root
během procesu výstavby, takže při příštím zavolání root
této metody nebude null
. V důsledku toho bude struktura mapy webu vrácena volajícímu, root
null
aniž by ji bylo nutné znovu vytvořit.
Pokud je null
kořen kořenem , vytvoří se struktura mapy webu z informací o produktu a kategorii. Mapa webu je vytvořena vytvořením SiteMapNode
instancí a následným vytvořením hierarchie prostřednictvím volání StaticSiteMapProvider
metody třídy s AddNode
. AddNode
provádí interní účetnictví a ukládá různé SiteMapNode
instance do Hashtable
. Než začneme vytvářet hierarchii, začneme voláním Clear
metody, která vymaže prvky z interní Hashtable
. Dále je ProductsBLL
metoda třídy s GetProducts
a výsledná ProductsDataTable
uložena v místních proměnných.
Vytvoření mapy webu začíná vytvořením kořenového uzlu a jeho přiřazením k root
. Přetížení konstruktoru s použitéhoSiteMapNode
zde a v tomto BuildSiteMap
průběhu je předáno následující informace:
- Odkaz na zprostředkovatele mapy webu (
this
). Key
SSiteMapNode
. Tato požadovaná hodnota musí být jedinečná pro každouSiteMapNode
hodnotu .Url
SSiteMapNode
.Url
je nepovinný, ale pokud je zadaný, každáSiteMapNode
hodnota sUrl
musí být jedinečná.Title
SSiteMapNode
, který je povinný.
Volání AddNode(root)
metody přidá SiteMapNode
root
do mapy webu jako kořen. Dále se vyčíslí ProductsDataTable
každý ProductRow
z nich. Pokud již existuje SiteMapNode
kategorie aktuálního produktu, odkazuje se na ni. V opačném případě se vytvoří nový SiteMapNode
objekt pro kategorii a přidá se jako podřízený objekt SiteMapNode``root
volání metody prostřednictvím AddNode(categoryNode, root)
metody. Po nalezení nebo vytvoření SiteMapNode
příslušného uzlu kategorie SiteMapNode
se vytvoří uzel pro aktuální produkt a přidá se jako podřízený uzel kategorie SiteMapNode
prostřednictvím AddNode(productNode, categoryNode)
. Všimněte si, že hodnota vlastnosti s kategorie SiteMapNode
Url
je ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID
v době, kdy je vlastnost produktu Url
SiteMapNode
přiřazena ~/SiteMapNode/ProductDetails.aspx?ProductID=productID
.
Poznámka
Produkty, které mají hodnotu databáze NULL
pro své CategoryID
jsou seskupeny do kategorie SiteMapNode
, jejíž Title
vlastnost je nastavena na None a jejichž Url
vlastnost je nastavena na prázdný řetězec. Rozhodl(a) jsem se nastavit Url
na prázdný řetězec, protože ProductBLL
metoda třídy s GetProductsByCategory(categoryID)
v současné době nemá schopnost vrátit pouze ty produkty s NULL
CategoryID
hodnotou. Také jsem chtěl ukázat, jak navigační ovládací prvky vykreslují SiteMapNode
objekt, který nemá hodnotu pro jeho Url
vlastnost. Doporučuji vám rozšířit tento kurz tak, že none SiteMapNode
s Url
vlastnost odkazuje na ProductsByCategory.aspx
, ale zobrazuje pouze produkty s NULL
CategoryID
hodnotami.
Po vytvoření mapy webu se do mezipaměti dat přidá libovolný objekt pomocí závislosti mezipaměti SQL na Categories
tabulkách a Products
prostřednictvím objektu AggregateCacheDependency
. Použití závislostí mezipaměti SQL jsme prozkoumali v předchozím kurzu Používání závislostí mezipaměti SQL. Vlastní poskytovatel mapy webu ale používá přetížení metody mezipaměti dat, Insert
kterou jsme ještě nezkoumali. Toto přetížení přijímá jako konečný vstupní parametr delegáta, který je volána při odebrání objektu z mezipaměti. Konkrétně předáme nového CacheItemRemovedCallback
delegáta , který odkazuje na metodu definovanou OnSiteMapChanged
dále ve NorthwindSiteMapProvider
třídě.
Poznámka
Reprezentace mapy webu v paměti se ukládá do mezipaměti prostřednictvím proměnné root
na úrovni třídy . Vzhledem k tomu, že existuje pouze jedna instance vlastní třídy zprostředkovatele mapy webu a protože tato instance je sdílena mezi všechna vlákna ve webové aplikaci, slouží tato proměnná třídy jako mezipaměť. Metoda BuildSiteMap
také používá mezipaměť dat, ale pouze jako prostředek k přijetí oznámení při změně podkladových databázových dat v Categories
tabulkách nebo Products
. Všimněte si, že hodnota vložená do mezipaměti dat je pouze aktuální datum a čas. Skutečná data mapy webu se do mezipaměti dat neumisťuje.
Metoda se BuildSiteMap
dokončí vrácením kořenového uzlu mapy webu.
Zbývající metody jsou poměrně jednoduché. GetRootNodeCore
zodpovídá za vrácení kořenového uzlu. Vzhledem k tomu BuildSiteMap
, že vrátí kořen, GetRootNodeCore
vrátí BuildSiteMap
jednoduše návratovou hodnotu s. Metoda OnSiteMapChanged
se nastaví root
zpět na null
při odebrání položky mezipaměti. S kořenem nastaveným zpět na null
, při BuildSiteMap
příštím vyvolání bude struktura mapy webu znovu vytvořena. CachedDate
Nakonec vlastnost vrátí hodnotu data a času uloženou v mezipaměti dat, pokud taková hodnota existuje. Tuto vlastnost může použít vývojář stránky k určení, kdy byla data mapy webu naposledy uložena do mezipaměti.
Krok 7: RegistraceNorthwindSiteMapProvider
Aby naše webová aplikace mohla používat zprostředkovatele mapy webu vytvořeného NorthwindSiteMapProvider
v kroku 6, musíme ho zaregistrovat v <siteMap>
části Web.config
. Konkrétně přidejte následující kód v elementu <system.web>
v Web.config
:
<siteMap defaultProvider="AspNetXmlSiteMapProvider">
<providers>
<add name="Northwind" type="NorthwindSiteMapProvider" />
</providers>
</siteMap>
Tento kód dělá dvě věci: zaprvé označuje, že předdefinovaný AspNetXmlSiteMapProvider
je výchozí zprostředkovatel mapy webu; za druhé zaregistruje vlastního zprostředkovatele mapy webu vytvořeného v kroku 6 s názvem Northwind.
Poznámka
U zprostředkovatelů mapy webu umístěných ve složce s App_Code
aplikace je hodnotou atributu type
jednoduše název třídy. Případně může být vlastní zprostředkovatel mapy webu vytvořen v samostatném projektu knihovny tříd s kompilovaným sestavením umístěným v adresáři s /Bin
webové aplikace. V takovém případě by hodnota atributu type
byla Obor názvů.ClassName, AssemblyName .
Po aktualizaci Web.config
se chvíli podívejte na libovolnou stránku z kurzů v prohlížeči. Všimněte si, že navigační rozhraní na levé straně stále zobrazuje oddíly a kurzy definované v Web.sitemap
nástroji . Je to proto, že jsme opustili AspNetXmlSiteMapProvider
výchozího poskytovatele. Abychom mohli vytvořit prvek navigačního uživatelského rozhraní, který používá NorthwindSiteMapProvider
, budeme muset explicitně určit, že se má použít zprostředkovatele mapy webu Northwind. Jak toho dosáhnout, uvidíme v kroku 8.
Krok 8: Zobrazení informací o mapě webu pomocí vlastního zprostředkovatele mapy webu
Po vytvoření a registraci vlastního zprostředkovatele mapy webu v Web.config
nástroji jsme připraveni přidat navigační ovládací prvky na Default.aspx
stránky , ProductsByCategory.aspx
a ProductDetails.aspx
ve SiteMapProvider
složce. Začněte otevřením Default.aspx
stránky a přetažením SiteMapPath
ze sady nástrojů na Designer. Ovládací prvek SiteMapPath se nachází v části Navigace panelu nástrojů.
Obrázek 16: Přidání siteMapPath do Default.aspx
(Kliknutím zobrazíte obrázek v plné velikosti)
Ovládací prvek SiteMapPath zobrazí popis cesty označující aktuální umístění stránky v mapě webu. V kurzu Stránky předlohy a Navigace na webu jsme do horní části stránky předlohy přidali cestu SiteMapPath.
Chvíli si tuto stránku prohlédněte v prohlížeči. SiteMapPath přidaná na obrázku 16 používá výchozího zprostředkovatele mapy webu a získává data z Web.sitemap
. Proto popis cesty zobrazuje domovskou > stránku Přizpůsobení mapy webu stejně jako popis cesty v pravém horním rohu.
Obrázek 17: Popis cesty používá výchozího zprostředkovatele mapy webu (kliknutím zobrazíte obrázek v plné velikosti)
Pokud chcete, aby cesta SiteMapPath přidaná na obrázku 16 používala vlastního zprostředkovatele mapy webu, který jsme vytvořili v kroku 6, nastavte jeho SiteMapProvider
vlastnost na Northwind, název, který jsme přiřadili k objektu NorthwindSiteMapProvider
v Web.config
. Designer bohužel dál používá výchozího poskytovatele mapy webu, ale pokud po provedení této změny vlastnosti navštívíte stránku přes prohlížeč, uvidíte, že popis cesty teď používá vlastního poskytovatele mapy webu.
Obrázek 18: Popis cesty teď používá vlastního zprostředkovatele NorthwindSiteMapProvider
mapy webu (kliknutím zobrazíte obrázek v plné velikosti)
Ovládací prvek SiteMapPath zobrazí na ProductsByCategory.aspx
stránkách a ProductDetails.aspx
funktivnější uživatelské rozhraní. Přidejte na tyto stránky SiteMapPath a SiteMapProvider
vlastnost v obou nastavíte na Northwind. V Default.aspx
části Nápoje klikněte na odkaz Zobrazit produkty a pak klikněte na odkaz Zobrazit podrobnosti pro Čaj Chai. Jak ukazuje obrázek 19, popis cesty obsahuje aktuální část mapy webu (Chai Tea) a její předky: Nápoje a všechny kategorie .
Obrázek 19: Popis cesty teď používá vlastního zprostředkovatele NorthwindSiteMapProvider
mapy webu (kliknutím zobrazíte obrázek v plné velikosti)
Další prvky uživatelského rozhraní navigace lze použít kromě SiteMapPath, například Menu a TreeView ovládací prvky. Stránky Default.aspx
, ProductsByCategory.aspx
a ProductDetails.aspx
ve stažení pro tento kurz, například všechny zahrnují ovládací prvky Nabídky (viz Obrázek 20). Podrobnější informace o ovládacích prvcích navigace a systému mapy webu v ASP.NET 2.0 najdete v části Sofistikované funkce navigace na webu ASP.NET 2.0 a Používání ovládacích prvků navigace na webu v ASP.NET 2.0 .
Obrázek 20: Ovládací prvek nabídky Seznamy každou z kategorií a produktů (kliknutím zobrazíte obrázek v plné velikosti)
Jak je uvedeno dříve v tomto kurzu, ke struktuře mapy webu je možné přistupovat programově prostřednictvím SiteMap
třídy. Následující kód vrátí kořen výchozího SiteMapNode
zprostředkovatele:
SiteMapNode root = SiteMap.RootNode;
Vzhledem k tomu, že AspNetXmlSiteMapProvider
je výchozí zprostředkovatel pro naši aplikaci, výše uvedený kód vrátí kořenový uzel definovaný v nástroji Web.sitemap
. Pokud chcete odkazovat na jiného poskytovatele mapy webu, než je výchozí, použijte SiteMap
vlastnost třídy s Providers
následujícím způsobem:
SiteMapNode root = SiteMap.Providers["name"].RootNode;
Kde název je název vlastního zprostředkovatele mapy webu (Northwind, pro naši webovou aplikaci).
Pokud chcete získat přístup k členu specifickému pro zprostředkovatele mapy webu, použijte SiteMap.Providers["name"]
k načtení instance zprostředkovatele a pak ji přetypujte na příslušný typ. Pokud chcete například zobrazit NorthwindSiteMapProvider
vlastnost s CachedDate
na stránce ASP.NET, použijte následující kód:
NorthwindSiteMapProvider customProvider =
SiteMap.Providers["Northwind"] as NorthwindSiteMapProvider;
if (customProvider != null)
{
DateTime? lastCachedDate = customProvider.CachedDate;
if (lastCachedDate != null)
LabelID.Text = "Site map cached on: " + lastCachedDate.Value.ToString();
else
LabelID.Text = "The site map is being reconstructed!";
}
Poznámka
Nezapomeňte otestovat funkci závislostí mezipaměti SQL. Po návštěvě Default.aspx
stránek , ProductsByCategory.aspx
a ProductDetails.aspx
přejděte na jeden z kurzů v části Úpravy, vkládání a odstraňování a upravte název kategorie nebo produktu. Pak se vraťte na jednu ze stránek ve SiteMapProvider
složce. Za předpokladu, že uplynul dostatek času, aby mechanismus dotazování zaznamenal změnu v podkladové databázi, měla by se mapa webu aktualizovat tak, aby zobrazovala nový název produktu nebo kategorie.
Souhrn
funkce mapy webu ASP.NET 2.0 s zahrnují SiteMap
třídu, řadu předdefinovaných navigačních webových ovládacích prvků a výchozího zprostředkovatele mapy webu, který očekává, že informace o mapě webu zůstanou zachovány v souboru XML. Abychom mohli používat informace o mapě webu z nějakého jiného zdroje, například z databáze, architektury aplikace nebo vzdálené webové služby, musíme vytvořit vlastního zprostředkovatele mapy webu. To zahrnuje vytvoření třídy, která je odvozena, přímo nebo nepřímo, z SiteMapProvider
třídy.
V tomto kurzu jsme viděli, jak vytvořit vlastního zprostředkovatele mapy webu, který mapu webu založí na informacích o produktech a kategoriích, které jsou vytříděné z architektury aplikace. Náš zprostředkovatel rozšířil StaticSiteMapProvider
třídu a zahrnoval vytvoření BuildSiteMap
metody, která načetla data, vytvořila hierarchii mapy webu a výslednou strukturu do mezipaměti v proměnné na úrovni třídy. Použili jsme závislost mezipaměti SQL s funkcí zpětného volání k zneplatnění struktury uložené v mezipaměti při úpravě podkladových Categories
dat nebo Products
dat.
Šťastné programování!
Další čtení
Další informace o tématech probíraných v tomto kurzu najdete v následujících zdrojích informací:
- Ukládání map webů v SQL Server a poskytovatel map webu SQL, na který jste čekali
- Sada nástrojů zprostředkovatele
- Sofistikované funkce navigace na webu ASP.NET 2.0
O autorovi
Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho najít na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na http://ScottOnWriting.NETadrese .
Zvláštní poděkování
Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byli Dave Gardner, Zack Jones, Teresa Murphy a Bernadette Leigh. Chcete si projít moje nadcházející články na WEBU MSDN? Pokud ano, dejte mi čáru na mitchell@4GuysFromRolla.comadresu .
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro