Sdílet prostřednictvím


Vytvoření vlastního databázově řízeného zprostředkovatele mapy webu (VB)

Scott Mitchell

Stáhnout PDF

Výchozí zprostředkovatel mapy webu v ASP.NET 2.0 načte 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čte data z vrstvy obchodní logiky, která zase načte data z databáze.

Úvod

ASP.NET 2.0 funkce mapy webu umožňuje vývojáři stránky definovat mapu webu webové aplikace v určitém trvalém médiu, například v souboru XML. Po definování mohou být data mapy webu přístupná prostřednictvím kódu programu 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 Ovládací prvky SiteMapPath, Menu a TreeView. Systém mapy webu používá model zprostředkovatele, aby bylo možné vytvořit a připojit k webové aplikaci různé implementace serializace mapy webu. Výchozí zprostředkovatel mapy webu, který se dodává s ASP.NET 2.0, zachovává strukturu mapy webu v souboru XML. Zpátky 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 jsme jeho XML o 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 však potřeba dynamičtější mapa webu. Představte si mapu webu zobrazenou na obrázku 1, kde se jednotlivé kategorie a produkty zobrazují jako oddíly ve struktuře webu. Při této mapě webu může návštěva webové stránky odpovídající kořenovému uzlu zobrazit seznam všech kategorií, zatímco při návštěvě konkrétní webové stránky kategorií by se zobrazily produkty dané kategorie a zobrazení konkrétní webové stránky produktu by zobrazily podrobnosti o produktu.

Kategorie a produkty make-up struktury mapy webu

Obrázek 1: Kategorie a produkty – make-up struktury mapy webu (kliknutím zobrazíte obrázek s plnou velikostí)

I když by tato struktura založená na kategoriích a produktech mohla být pevně zakódovaná do Web.sitemap souboru, soubor by se měl aktualizovat při každém přidání kategorie nebo produktu, odebrání nebo přejmenování. V důsledku toho by byla údržba mapy webu značně zjednodušená, pokud by byla její struktura načtena z databáze nebo ideálně z vrstvy obchodní logiky architektury aplikace. Díky tomu se při přidání, přejmenování nebo odstranění produktů a kategorií mapa webu automaticky aktualizuje tak, aby odrážela tyto změny.

Vzhledem k tomu, ASP.NET 2.0 s serializace mapy webu je postavena na základě modelu poskytovatele, můžeme vytvořit vlastního zprostředkovatele mapy webu, který vezme svá data z alternativního úložiště dat, jako je databáze nebo architektura. V tomto kurzu vytvoříme vlastního zprostředkovatele, který načte data z BLL. Pojďme začít!

Poznámka:

Vlastní zprostředkovatel mapy webu vytvořený v tomto kurzu je úzce propojený s architekturou a datovým modelem aplikace. Jeff Prosise s Storing Site Maps in SQL Server and The SQL Site Map Provider You ve Been Waiting For articles examine a generalized approach to storing site map data in SQL Server.

Krok 1: Vytvoření vlastních webových stránek zprostředkovatele mapy webu

Než začneme vytvářet vlastního zprostředkovatele mapy webu, nejdřív přidáme 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 přidružit každou stránku ke stránce předlohy Site.master :

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

Do složky přidejte CustomProviders také podsložku App_Code .

Přidání stránek ASP.NET pro kurzy související s poskytovatelem mapy webu

Obrázek 2: Přidání ASP.NET stránek pro kurzy související s poskytovatelem mapy webu

Vzhledem k tomu, že pro tuto část existuje jenom jeden kurz, nemusíme Default.aspx vypisovat kurzy oddílů. Default.aspx Místo toho zobrazí kategorie v ovládacím prvku GridView. Budeme se s tím zabývat v kroku 2.

V dalším kroku aktualizujte Web.sitemap 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.sitemapsi chvíli prohlédněte web kurzů prostřednictvím prohlížeče. Nabídka vlevo teď obsahuje položku pro jediný kurz poskytovatele mapy webu.

Mapa webu teď obsahuje položku pro kurz zprostředkovatele mapy webu.

Obrázek 3: Mapa webu teď obsahuje položku pro kurz zprostředkovatele mapy webu

Hlavním cílem tohoto kurzu je ilustrovat vytvoření vlastního zprostředkovatele mapy webu a konfiguraci 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 na mapě webu může zadat adresu URL. Pro naši mapu webu bude ~/SiteMapProvider/Default.aspxadresa 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 každý uzel mapy webu produktu bude 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, ProductsByCategory.aspxa ProductDetails.aspx stránky. Tyto stránky jsou dokončeny v krocích 2, 3 a 4. Vzhledem k tomu, že tah tohoto kurzu je na poskytovatelích map webu a od předchozích kurzů jsme se zabývali vytvářením těchto typů sestav předlohy a podrobností s více stránkami, pospěšíme si kroky 2 až 4. Pokud potřebujete aktualizovatel při vytváření sestav předlohy a podrobností, které pokrývají více stránek, vraťte se k kurzu Filtrování předlohy a podrobností napříč dvěma stránkami .

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ů do Návrháře a nastavte ho ID na Categories. Z inteligentní značky GridView vytvořte vazbu na nový ObjectDataSource pojmenovaný CategoriesDataSource a nakonfigurujte ho tak, aby načetl svá 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 (Žádné).

Konfigurace ObjectDataSource pro vrácení kategorií pomocí metody GetCategories

Obrázek 4: Konfigurace ObjectDataSource pro vrácení kategorií pomocí GetCategories metody (kliknutím zobrazíte obrázek s plnou velikostí)

Nastavte rozevírací seznamy na kartách UPDATE, INSERT a DELETE na (Žádné).

Obrázek 5: Nastavení rozevíracích seznamů na kartách UPDATE, INSERT a DELETE na (Žádné) (Kliknutím zobrazíte obrázek v plné velikosti)

Po dokončení průvodce konfigurací zdroje dat sada Visual Studio přidá BoundField pro CategoryID, CategoryName, Description, NumberOfProductsa BrochurePath. Upravte GridView tak, aby obsahoval CategoryName pouze a Description BoundFields a aktualizovat CategoryName BoundField s HeaderText vlastnost Category .

Dále přidejte HyperLinkField a umístěte ho tak, aby bylo pole nejvíce vlevo. DataNavigateUrlFields Nastavte vlastnost CategoryID na hodnotu a DataNavigateUrlFormatString vlastnost na ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0}hodnotu . Text Nastavte vlastnost zobrazit produkty .

Přidání HyperLinkFieldu do objektu Categories GridView

Obrázek 6: Přidání HyperLinkFieldu do gridview Categories

Po vytvoření ObjectDataSource a přizpůsobení polí GridView s budou dva ovládací prvky deklarativní revize 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 znázorňuje Default.aspx zobrazení v prohlížeči. Kliknutím na odkaz Zobrazit produkty kategorie přejdete na odkaz , který ProductsByCategory.aspx?CategoryID=categoryIDvytvoříme v kroku 3.

Každá kategorie je uvedená společně s odkazem Zobrazit produkty.

Obrázek 7: Každá kategorie je uvedena společně s odkazem Na produkty zobrazení (kliknutím zobrazíte obrázek v plné velikosti).

Krok 3: Výpis produktů vybrané kategorie

ProductsByCategory.aspx Otevřete stránku a přidejte GridView a pojmete ji ProductsByCategory. Z inteligentní značky vytvořte vazbu GridView na nový 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.

Použití třídy ProductsBLL s GetProductsByCategoryID(categoryID) – metoda

Obrázek 8: Použití ProductsBLL metody třídy GetProductsByCategoryID(categoryID) (kliknutím zobrazíte obrázek s plnou velikostí)

Poslední krok v průvodci konfigurací zdroje dat zobrazí výzvu ke zdroji parametrů pro ID kategorie. Vzhledem k tomu, že se tyto informace předávají prostřednictvím pole CategoryIDřetězce dotazu , vyberte z rozevíracího seznamu řetězec dotazu a zadejte CategoryID do textového pole QueryStringField, jak je znázorněno na obrázku 9. Dokončete průvodce kliknutím na Dokončit.

Použití pole řetězce dotazu CategoryID pro parametr categoryID

Obrázek 9: Použití CategoryID pole řetězce dotazu pro parametr categoryID (Kliknutím zobrazíte obrázek s plnou velikostí)

Po dokončení průvodce visual Studio přidá odpovídající BoundFields a CheckBoxField do GridView pro pole s daty produktu. Odeberte všechny kromě ProductNameUnitPrice, a SupplierName BoundFields. Přizpůsobte si tyto tři vlastnosti BoundFields HeaderText tak, aby si přečetly produkt, cenu a dodavatele. Naformátujte UnitPrice BoundField jako měnu.

Dále přidejte HyperLinkField a přesuňte ho na pozici úplně vlevo. Nastavte jeho Text vlastnost zobrazit podrobnosti, jeho DataNavigateUrlFields vlastnost na ProductIDa jeho DataNavigateUrlFormatString vlastnost na ~/SiteMapProvider/ProductDetails.aspx?ProductID={0}.

Přidání hyperlinkfieldu podrobností zobrazení, které odkazuje na ProductDetails.aspx

Obrázek 10: Přidání hyperlinkfieldu podrobností zobrazení, které odkazuje na ProductDetails.aspx

Po provedení těchto přizpůsobení by deklarativní kód GridView a ObjectDataSource měly vypadat přibližně 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 k prohlížení Default.aspx v prohlížeči a klikněte na odkaz Zobrazit produkty pro nápoje. Tím přejdete na ProductsByCategory.aspx?CategoryID=1zobrazení názvů, cen 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 vrácení uživatelů na stránku výpisu kategorií (Default.aspx) a ovládací prvek DetailsView nebo FormView, který zobrazuje název a popis vybrané kategorie.

Zobrazí se názvy nápojů, ceny a dodavatelé.

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 ProductDetails.aspxse zobrazí podrobnosti o vybraných produktech. Otevřete ProductDetails.aspx a přetáhněte DetailsView z panelu nástrojů do Návrháře. Nastavte DetailsView s ID vlastnost ProductInfo a vymazat jeho Height a Width vlastnosti hodnoty. Z inteligentní značky vytvořte vazbu DetailsView na nový ObjectDataSource pojmenovaný ProductDataSource, konfigurace ObjectDataSource pro načtení dat 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é).

Konfigurace ObjectDataSource pro použití metody GetProductByProductID(productID)

Obrázek 12: Konfigurace ObjectDataSource pro použití GetProductByProductID(productID) metody (kliknutím zobrazíte obrázek s plnou velikostí)

Poslední krok průvodce konfigurací zdroje dat zobrazí výzvu ke zdroji parametru ProductID . Vzhledem k tomu, že tato data procházejí polem ProductIDřetězce dotazu , nastavte rozevírací seznam na QueryString a QueryStringField textové pole ProductID. Nakonec dokončete průvodce kliknutím na tlačítko Dokončit.

Konfigurace parametru PRODUCTID pro načtení jeho hodnoty z pole řetězce dotazu PRODUCTID

Obrázek 13: Konfigurace parametru PRODUCTID pro načtení jeho hodnoty z ProductID pole řetězce dotazu (kliknutím zobrazíte obrázek s plnou velikostí)

Po dokončení průvodce konfigurací zdroje dat vytvoří Visual Studio odpovídající BoundFields a CheckBoxField v DetailsView pro pole s daty produktu. Odeberte pole ProductID, SupplierIDa CategoryID BoundFields a nakonfigurujte zbývající pole podle potřeby. Po několika estetických konfiguracích vypadaly deklarativní značky DetailsView a ObjectDataSource 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>

Chcete-li otestovat tuto stránku, vraťte se a Default.aspx klikněte na Zobrazit produkty pro kategorii Nápoje. V seznamu nápojů klikněte na odkaz Zobrazit podrobnosti pro Chai Čaj. Tím přejdete na ProductDetails.aspx?ProductID=1, který zobrazuje podrobnosti Chai Tea s (viz obrázek 14).

Chai Tea s Dodavatel, Kategorie, Cena a Další informace jsou zobrazeny

Obrázek 14: Chai Tea s Dodavatel, Kategorie, Cena a Další informace jsou zobrazeny (Kliknutím zobrazíte obrázek v plné velikosti)

Krok 5: Principy vnitřních fungování zprostředkovatele mapy webu

Mapa webu je reprezentována v paměti webového SiteMapNode serveru jako kolekce 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 obvykle mají odpovídající webovou stránku. V důsledku toho třída má vlastnosti, SiteMapNode jako Titleje , Urla Description, které poskytují informace pro oddíl představujeSiteMapNode. Existuje také Key vlastnost, která jednoznačně identifikuje každý SiteMapNode v hierarchii, stejně jako vlastnosti použité k vytvoření této hierarchie ChildNodes, , ParentNode, NextSiblingPreviousSiblinga tak dále.

Obrázek 15 znázorňuje obecnou strukturu mapy webu z obrázku 1, ale s podrobnostmi implementace, které jsou načrtnuté podrobněji.

Každý uzel SiteMapNode má vlastnosti, jako je název, adresa URL, klíč a tak dále.

Obrázek 15: Každá SiteMapNode má vlastnosti like Title, Url, Keya tak dále (kliknutím zobrazíte obrázek s plnou velikostí)

Mapa webu je přístupná prostřednictvím SiteMap třídy v System.Web oboru názvů. Tato vlastnost třídy RootNode 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. Tato třída se interně používá ASP.NET 2.0 navigační webové ovládací prvky.

Při přístupu k vlastnostem SiteMap třídy 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 třída určuje, SiteMap který zprostředkovatel mapy webu se má použít pro serializaci. Ve výchozím nastavení se XmlSiteMapProvider používá třída , která čte strukturu mapy webu z správně formátovaného souboru XML. S trochou práce ale můžeme vytvořit vlastního poskytovatele mapy webu.

Všichni zprostředkovatelé map webů 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í implementace. Druhá třída, StaticSiteMapProviderrozšiřuje SiteMapProvider třídu a obsahuje robustnější implementaci potřebných funkcí. Interně ukládá SiteMapNode instance mapy webu do Hashtable a poskytuje metody, StaticSiteMapProvider jako AddNode(child, parent)je , RemoveNode(siteMapNode), a Clear() které přidávají a odebírat SiteMapNode do interní Hashtable. XmlSiteMapProvider je odvozen z StaticSiteMapProvider.

Při vytváření vlastního zprostředkovatele mapy webu, který rozšiřuje , existují dvě abstraktní metody, které musí být přepsány StaticSiteMapProvider: BuildSiteMap a GetRootNodeCore. BuildSiteMap, jak už název napovídá, je zodpovědný za načtení struktury mapy webu z trvalého úložiště a jeho vytvoření v paměti. GetRootNodeCore vrátí kořenový uzel v mapě webu.

Než webová aplikace může použít 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 čitelný název č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 pro název a typ v kroku 7.

Třída zprostředkovatele mapy webu je vytvořena při prvním přístupu z SiteMap třídy a zůstává 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án z více souběžných návštěvníků webu, je nezbytné, aby metody poskytovatele byly bezpečné pro přístup z více vláken.

Z důvodů výkonu a škálovatelnosti je důležité uložit strukturu mapy webu v paměti do mezipaměti a vrátit tuto strukturu uloženou v mezipaměti, místo aby se znovu vytvořila při BuildSiteMap každém vyvolání metody. BuildSiteMap v závislosti na ovládacích prvcích navigace, které se používají na stránce, a hloubky struktury mapy webu může být volána několikrát na každý uživatel požadavek na stránku. Pokud v každém případě neupamějíme strukturu mapy webu do BuildSiteMap mezipaměti, při každém vyvolání bychom museli znovu načíst informace o produktu a kategorii z architektury (což by vedlo k dotazu na databázi). Jak jsme si probrali v předchozích kurzech ukládání do mezipaměti, můžou se data uložená v mezipaměti stát zastaralou. K tomu můžeme použít vypršení časového limitu nebo vypršení platnosti založeného na mezipaměti SQL.

Poznámka:

Zprostředkovatel mapy webu může volitelně přepsat metoduInitialize. Initialize je vyvolána při prvním vytvoření instance zprostředkovatele mapy webu a je předán všechny vlastní atributy přiřazené zprostředkovateli v Web.config elementu <add> jako: <add name="name" type="type" customAttribute="value" />. Je užitečné, pokud chcete povolit vývojáři stránky zadat různá nastavení související s poskytovatelem mapy webu, aniž byste museli upravovat kód zprostředkovatele. Pokud bychom například četli data o kategoriích a produktech přímo z databáze, a ne prostřednictvím architektury, měli bychom chtít, aby vývojář stránky zadal databázi připojovací řetězec místo Web.config použití pevně zakódované hodnoty 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 této metody najdete v článku o ukládání map webu v SQL Serveru od Jeffa Prosise.

Krok 6: Vytvoření vlastního zprostředkovatele mapy webu

Abychom vytvořili 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, abyste do složky přidali CustomProviders složku App_Code – přidejte do této složky novou třídu s názvem NorthwindSiteMapProvider. Do třídy přidejte následující kód 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

Začněme zkoumáním této metody třídyBuildSiteMap, 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ákenm v krokování mezi sebou s toky.

Proměnná root na úrovni SiteMapNode třídy slouží k ukládání struktury mapy webu do mezipaměti. Když se mapa webu vytvoří poprvé nebo poprvé po úpravě podkladových dat, root vytvoří Nothing se struktura mapy webu. Kořenový uzel mapy webu je přiřazen root během procesu vytváření tak, aby při příštím zavolání root této metody nebyl Nothing. Pokud root tedy není Nothing struktura mapy webu vrácena volajícímu, aniž by bylo nutné ji znovu vytvořit.

Pokud je Nothingkořen, 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 AddNode . AddNodeprovádí interní účetnictví a ukládá seřazené SiteMapNode instance do .Hashtable Než začneme vytvářet hierarchii, začneme voláním Clear metody, která vymaže prvky z interního Hashtable. Dále se ProductsBLL metoda třídy s GetProducts a výsledná ProductsDataTable metoda ukládají v místních proměnných.

Konstrukce mapy webu začíná vytvořením kořenového uzlu a jeho přiřazením .root Přetížení konstruktoru použitého SiteMapNode zde a v tomto případě BuildSiteMap se předává následující informace:

  • Odkaz na zprostředkovatele mapy webu (Me).
  • KeyS SiteMapNode . Tato požadovaná hodnota musí být pro každou SiteMapNodehodnotu jedinečná .
  • UrlS SiteMapNode . Url je nepovinný, ale pokud je zadaná, musí být každá SiteMapNode Url hodnota jedinečná.
  • Jedná se o SiteMapNode s Title, který je povinný.

Volání AddNode(root) metody přidá SiteMapNode root do mapy webu jako kořen. V dalším kroku se vyčíslí každý ProductRow z nich ProductsDataTable . Pokud již existuje SiteMapNode kategorie aktuálního produktu, odkazuje se na ni. V opačném případě se vytvoří nová SiteMapNode kategorie a přidá se jako podřízený volání SiteMapNode``root metody AddNode(categoryNode, root) . Po nalezení nebo vytvoření SiteMapNode příslušného uzlu kategorie SiteMapNode se vytvoří 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 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 jehož Url vlastnost je nastavena na prázdný řetězec. Rozhodl jsem se nastavit Url prázdný řetězec, protože ProductBLL metoda třídy GetProductsByCategory(categoryID) v současné době nemá schopnost vrátit pouze ty produkty s NULL CategoryID hodnotou. Také jsem chtěl předvést, jak ovládací prvky navigace vykreslují SiteMapNode , která nemá hodnotu pro jeho Url vlastnost. Doporučuji vám rozšířit tento kurz tak, aby 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 objektu Categories a Products tabulek AggregateCacheDependency . Prozkoumali jsme použití závislostí mezipaměti SQL v předchozím kurzu pomocí závislostí mezipaměti SQL. Vlastní zprostředkovatel mapy webu však používá přetížení metody mezipaměti Insert dat, kterou jsme zatím prozkoumali. Toto přetížení přijímá jako konečný vstupní parametr delegát, který je volán při odebrání objektu z mezipaměti. Konkrétně předáme novému CacheItemRemovedCallback delegátu , který odkazuje na metodu OnSiteMapChanged definovanou 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é rootna ú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šemi vlákny webové aplikace, tato proměnná třídy slouží jako mezipaměť. Metoda BuildSiteMap také používá mezipaměť dat, ale pouze jako prostředek pro příjem oznámení, když se podkladová data databáze v Categories tabulkách změní 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 neuloží do mezipaměti dat.

Metoda BuildSiteMap se 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 jednoduše vrátí BuildSiteMap návratovou hodnotu. Metoda OnSiteMapChanged se nastaví root zpět při Nothing odebrání položky mezipaměti. Při zpětném Nothingnastavení kořenového adresáře se při příštím BuildSiteMap vyvolání struktury mapy webu znovu sestaví. CachedDate Nakonec vrátí vlastnost 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 v mezipaměti.

Krok 7: RegistraceNorthwindSiteMapProvider

Aby naše webová aplikace mohla používat NorthwindSiteMapProvider poskytovatele mapy webu vytvořeného v kroku 6, musíme ji zaregistrovat v <siteMap> části Web.config. Konkrétně přidejte do elementu <system.web> Web.confignásledující kód:

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

Tento kód dělá dvě věci: nejprve označuje, že předdefinovaný AspNetXmlSiteMapProvider je výchozí zprostředkovatel mapy webu; 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 aplikace App_Code je hodnota type atributu jednoduše název třídy. Případně mohl 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 webové aplikace /Bin . V takovém případě by hodnota atributu type byla Obor názvů.ClassName, AssemblyName .

Po aktualizaci Web.configsi chvilku prohlédněte libovolnou stránku z kurzů v prohlížeči. Všimněte si, že navigační rozhraní vlevo stále zobrazuje oddíly a kurzy definované v Web.sitemap. Je to proto, že jsme zůstali AspNetXmlSiteMapProvider jako výchozí zprostředkovatel. Abychom mohli vytvořit prvek uživatelského rozhraní navigace, který používá NorthwindSiteMapProvider, budeme muset explicitně určit, že by se měl použít poskytovatel mapy webu Northwind. V kroku 8 se dozvíme, jak toho dosáhnout.

Krok 8: Zobrazení informací o mapě webu pomocí vlastního zprostředkovatele mapy webu

S vlastním poskytovatelem mapy webu vytvořeným a zaregistrovaným v Web.config, jsme připraveni přidat navigační ovládací prvky do Default.aspxProductsByCategory.aspxsložky a ProductDetails.aspx stránky ve SiteMapProvider složce. Začněte otevřením Default.aspx stránky a přetažením SiteMapPath ze sady nástrojů do Návrháře. Ovládací prvek SiteMapPath se nachází v části Navigace panelu nástrojů.

Přidání cesty SiteMapPath k Default.aspx

Obrázek 16: Přidání cesty SiteMapPath (Default.aspxkliknutím zobrazíte obrázek v plné velikosti)

Ovládací prvek SiteMapPath zobrazí popis cesty označující umístění aktuální stránky v mapě webu. Do horní části stránky předlohy jsme přidali cestu SiteMapPath v kurzu Stránky předlohy a Navigace na webu.

Chvilku si tuto stránku prohlédněte v prohlížeči. SiteMapPath přidaný na obrázek 16 používá výchozího zprostředkovatele mapy webu, který načítá data z Web.sitemap. Proto popis cesty zobrazuje > přizpůsobení mapy webu, stejně jako popis cesty v pravém horním rohu.

Popis cesty používá výchozího zprostředkovatele mapy webu.

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 mít SiteMapPath přidaný na obrázku 16, použijte 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 in Web.config. Návrhář bohužel nadále používá výchozího poskytovatele mapy webu, ale pokud stránku navštívíte v prohlížeči po provedení této změny vlastnosti, uvidíte, že popis cesty teď používá vlastního poskytovatele mapy webu.

Snímek obrazovky znázorňující, jak popis cesty zobrazuje vlastního zprostředkovatele mapy webu

Obrázek 18: Popis cesty teď používá vlastního zprostředkovatele NorthwindSiteMapProvider mapy webu (kliknutím zobrazíte obrázek plné velikosti).

Ovládací prvek SiteMapPath zobrazí na stránkách více funkční uživatelské rozhraní ProductsByCategory.aspx ProductDetails.aspx . Přidat SiteMapPath na tyto stránky, nastavení SiteMapProvider vlastnosti v obou northwind. Klikněte Default.aspx na odkaz Zobrazit produkty pro nápoje a potom na odkaz Zobrazit podrobnosti pro Chai Čaj. Jak ukazuje obrázek 19, popis cesty zahrnuje aktuální část mapy webu (Chai Čaj) a její předky: Nápoje a Všechny kategorie .

Snímek obrazovky znázorňující, jak popis cesty zobrazuje aktuální oddíl mapy webu (Chai Čaj) a jeho nadřazené položky (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 s plnou velikostí).

Další prvky uživatelského rozhraní navigace lze použít kromě SiteMapPath, například Menu a TreeView ovládací prvky. Položky Default.aspx, ProductsByCategory.aspxa ProductDetails.aspx stránky ke stažení pro tento kurz, například všechny ovládací prvky nabídky (viz obrázek 20). Podrobnější informace o ovládacích prvcích navigace na navigačním panelu a systému mapy webu v ASP.NET 2.0 najdete v části ASP.NET 2.0 Sofistikované funkce navigace na webu a oddíl Using Site Navigation Controls (Používání ovládacích prvků navigace webu) v rychlých startech ASP.NET 2.0.

Ovládací prvek nabídky uvádí jednotlivé kategorie a produkty.

Obrázek 20: Ovládací prvek nabídky obsahuje seznam jednotlivých kategorií a produktů (kliknutím zobrazíte obrázek v plné velikosti).

Jak už bylo zmíněno dříve v tomto kurzu, struktura mapy webu je přístupná prostřednictvím kódu programu prostřednictvím SiteMap třídy. Následující kód vrátí kořen SiteMapNode výchozího zprostředkovatele:

Dim root As SiteMapNode = SiteMap.RootNode

AspNetXmlSiteMapProvider Vzhledem k tomu, že je výchozím poskytovatelem naší aplikace, výše uvedený kód by vrátil kořenový uzel definovaný v Web.sitemap. Pokud chcete odkazovat na jiného zprostředkovatele mapy webu než výchozí, použijte SiteMap vlastnost třídyProviders, například takto:

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

Kde název je název vlastního poskytovatele 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 jeho přetypování na příslušný typ. Pokud chcete například zobrazit NorthwindSiteMapProvider vlastnost ASP.NET CachedDate stránky, použijte následující kód:

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

Poznámka:

Nezapomeňte otestovat funkci závislostí mezipaměti SQL. Po návštěvě oddílu Default.aspx, ProductsByCategory.aspxa ProductDetails.aspx stránek přejděte na některý z kurzů v části Úpravy, Vložení a Odstraně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 pro mechanismus dotazování uplynul dostatek času, aby si poznamenal změnu podkladové databáze, měla by se mapa webu aktualizovat tak, aby zobrazovala název nového produktu nebo kategorie.

Shrnutí

ASP.NET 2.0 funkcí mapy webu zahrnuje SiteMap třídu, řadu předdefinovaných navigačních webových ovládacích prvků a výchozího poskytovatele mapy webu, který očekává, že informace mapy webu se zachovají do souboru XML. Abychom mohli použít informace o mapě webu z nějakého jiného zdroje, například z databáze, architektury aplikace nebo vzdálené webové služby, potřebujeme 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ý na základě mapy webu na základě informací o produktu a kategoriích vyčíslených z architektury aplikace. Náš poskytovatel rozšířil StaticSiteMapProvider třídu a zahrnoval vytvoření BuildSiteMap metody, která načetla data, vytvořila hierarchii mapy webu a do mezipaměti výslednou strukturu v proměnné na úrovni třídy. Závislost mezipaměti SQL s funkcí zpětného volání jsme použili 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í:

O autorovi

Scott Mitchell, autor sedmi knih ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, trenér a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 za 24 hodin. Je dostupný na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím svého blogu, který lze najít na http://ScottOnWriting.NET.

Zvláštní díky

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Vedoucí hodnotící tohoto kurzu byli Dave Gardner, Zack Jones, Teresa Murphy a Bernadette Leigh. Chcete si projít nadcházející články MSDN? Pokud ano, zahoďte mi řádek na mitchell@4GuysFromRolla.com.