Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
által Scott Mitchell
A ASP.NET 2.0 alapértelmezett helytérkép-szolgáltatója egy statikus XML-fájlból kéri le az adatait. Bár az XML-alapú szolgáltató számos kis- és közepes méretű webhelyhez alkalmas, a nagyobb webalkalmazások dinamikusabb webhelytérképet igényelnek. Ebben az oktatóanyagban létrehozunk egy egyéni webhelyleképezési szolgáltatót, amely lekéri az adatait az üzleti logikai rétegből, amely viszont adatokat kér le az adatbázisból.
Bevezetés
ASP.NET 2.0-s webhelytérkép funkció lehetővé teszi a lapfejlesztők számára, hogy egy webalkalmazás webhelytérképét valamilyen állandó adathordozón, például EGY XML-fájlban definiálják. A definiálás után a helytérkép adatai programozott módon érhetők el a SiteMap névtér osztályánSystem.Web vagy számos navigációs webvezérlőn keresztül, például a SiteMapPath, a Menü és a TreeView vezérlőn keresztül. A webhelytérkép-rendszer a szolgáltatói modellt használja, hogy különböző helytérkép-szerializálási implementációk hozhatók létre és csatlakoztathatók egy webalkalmazáshoz. A ASP.NET 2.0-val rendelkező alapértelmezett helytérkép-szolgáltató megőrzi a helytérkép struktúráját egy XML-fájlban. A Mesterlapok és a Webhelynavigációs oktatóanyagban létrehoztunk egy fájlt Web.sitemap , amely tartalmazta ezt a struktúrát, és minden új oktatóanyagszakaszra frissítettük az XML-t.
Az alapértelmezett XML-alapú webhelyleképezési szolgáltató jól működik, ha a helytérkép struktúrája meglehetősen statikus, például az oktatóanyagok esetében. Sok esetben azonban dinamikusabb webhelytérképre van szükség. Vegye figyelembe az 1. ábrán látható webhelytérképet, ahol minden kategória és termék szakaszként jelenik meg a webhely szerkezetében. Ezen a webhelytérképen a gyökércsomópontnak megfelelő weblap felkeresése felsorolhatja az összes kategóriát, míg egy adott kategória weblapjának felkeresése az adott kategória termékeit listázná, és egy adott termék weblapjának megtekintése megjelenítené a termék adatait.
1. ábra: A kategóriák és termékek a webhelytérkép struktúráját alkotják (ide kattintva megtekintheti a teljes méretű képet)
Bár ez a kategória- és termékalapú struktúra nehezen kódolható a Web.sitemap fájlba, a fájlt minden alkalommal frissíteni kell, amikor hozzáadnak, eltávolítanak vagy átneveznek egy kategóriát vagy terméket. Következésképpen a helytérkép karbantartása jelentősen egyszerűbb lenne, ha a struktúrát az adatbázisból vagy ideális esetben az alkalmazás architektúrájának üzleti logikai rétegéből kérnék le. Így a termékek és kategóriák hozzáadása, átnevezése vagy törlése során a webhelytérkép automatikusan frissül, hogy tükrözze ezeket a változásokat.
Mivel ASP.NET 2.0-s webhelytérkép szerializálása a szolgáltatói modellen alapul, létrehozhatunk egy saját egyéni webhelytérkép-szolgáltatót, amely egy másik adattárból, például az adatbázisból vagy az architektúrából szerzi be az adatait. Ebben az oktatóanyagban létrehozunk egy egyéni szolgáltatót, amely lekéri az adatait a BLL-ből. Lássunk hozzá!
Megjegyzés:
Az oktatóanyagban létrehozott egyéni webhelytérkép-szolgáltató szorosan kapcsolódik az alkalmazás architektúrához és adatmodellhez. Jeff Prosise Tárolási helytérképek az SQL Serverben és Az SQL webhelytérkép-szolgáltató, amire várt című cikkei a webhelytérkép-adatok SQL Serverben való tárolásának általános megközelítését vizsgálják.
1. lépés: Az egyéni webhelytérkép-szolgáltató weblapjainak létrehozása
Mielőtt létrehoznánk egy egyéni webhelytérkép-szolgáltatót, először vegyük fel az oktatóanyaghoz szükséges ASP.NET lapokat. Első lépésként adjon hozzá egy új mappát.SiteMapProvider Ezután adja hozzá a következő ASP.NET lapokat a mappához, és mindenképpen társítsa az egyes lapokat a Site.master mesterlaphoz:
Default.aspxProductsByCategory.aspxProductDetails.aspx
Egy CustomProviders almappát is adjon hozzá a App_Code mappához.
2. ábra: A webhelytérkép Provider-Related oktatóanyagok ASP.NET lapjainak hozzáadása
Mivel ehhez a szakaszhoz csak egy oktatóanyag tartozik, nem kell Default.aspx felsorolnunk a szakasz oktatóanyagait.
Default.aspx Ehelyett egy GridView-vezérlőben jeleníti meg a kategóriákat. Ezt a 2. lépésben fogjuk kezelni.
Ezután frissítsen Web.sitemap , hogy hivatkozzon a Default.aspx lapra. Pontosabban adja hozzá a következő jelölést a gyorsítótárazás <siteMapNode> után:
<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." />
A frissítés Web.sitemapután szánjon egy kis időt az oktatóanyagok webhelyének megtekintésére egy böngészőben. A bal oldali menü most már tartalmaz egy elemet az egyetlen webhelytérkép-szolgáltató oktatóanyagához.
3. ábra: A webhelytérkép most már tartalmaz egy bejegyzést a webhelytérkép-szolgáltató oktatóanyagához
Ez az oktatóanyag elsősorban egy egyéni webhelytérkép-szolgáltató létrehozását és egy webalkalmazás konfigurálását mutatja be a szolgáltató használatára. Létrehozunk egy szolgáltatót, amely egy gyökércsomópontot tartalmazó webhelytérképet ad vissza az egyes kategóriákhoz és termékekhez tartozó csomóponttal együtt, az 1. ábrán látható módon. Általánosságban elmondható, hogy a helytérkép minden csomópontja megadhat egy URL-címet. A webhelytérkép esetében a gyökércsomópont URL-címe lesz ~/SiteMapProvider/Default.aspx, amely felsorolja az adatbázis összes kategóriáját. A webhelytérkép minden kategóriacsomópontjához tartozik egy URL-cím, ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryIDamely a megadott kategóriaazonosítóban szereplő összes terméket listázni fogja. Végül minden termékwebhely-térképcsomópont arra ~/SiteMapProvider/ProductDetails.aspx?ProductID=productIDmutat, amely megjeleníti az adott termék részleteit.
A kezdéshez létre kell hoznunk a Default.aspx, ProductsByCategory.aspx, és ProductDetails.aspx lapokat. Ezek a lapok a 2., 3. és 4. lépésben fejeződnek be. Mivel ennek az oktatóanyagnak a tolóereje a webhelytérkép-szolgáltatókon van, és mivel a korábbi oktatóanyagok foglalkoztak az ilyen típusú többoldalas master/detail jelentések létrehozásával, a 2–4. lépést fogjuk elvégezni. Ha felfrissítené tudását a több oldalt felölelő fő-/részletjelentések létrehozásával kapcsolatban, tekintsen vissza a Mester/Részletek szűrése két oldalon oktatóanyagra.
2. lépés: Kategóriák listájának megjelenítése
Nyissa meg a Default.aspx oldalt a SiteMapProvider mappában, húzzon egy GridView-t az eszközkészletből a Tervezőre, majd állítsa be a ID értékét Categories-ra. A GridView intelligens címkéje alapján kösse hozzá egy új ObjectDataSource-hoz, CategoriesDataSource és konfigurálja úgy, hogy az osztály s CategoriesBLL metódusával kérje le az GetCategories adatait. Mivel ez a GridView csak megjeleníti a kategóriákat, és nem biztosít adatmódosítási képességeket, állítsa a legördülő listákat az UPDATE, INSERT és DELETE füleken a (Nincs) értékre.
4. ábra: Az ObjectDataSource konfigurálása kategóriák visszaadásához a GetCategories metódus használatával (kattintson ide a teljes méretű kép megtekintéséhez)
5. ábra: Állítsa a Drop-Down listákat az UPDATE, INSERT és DELETE tabulátorokban a (Nincs) értékre (kattintson ide a teljes méretű kép megtekintéséhez)
Az Adatforrás konfigurálása varázsló befejezése után a Visual Studio hozzáad egy BoundFieldet a CategoryID, CategoryName, Description, NumberOfProducts és BrochurePath mezőkhöz. Szerkessze a GridView-t úgy, hogy csak a CategoryName és Description BoundFields-t tartalmazza, és frissítse a CategoryName BoundField HeaderText tulajdonságát Kategóriára.
Ezután adjon hozzá egy HyperLinkFieldet, és helyezze el úgy, hogy az legyen a bal oldali mező. Állítsa be a DataNavigateUrlFields tulajdonságot CategoryID értékre, és a DataNavigateUrlFormatString tulajdonságot ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0} értékre. Állítsa be a Text tulajdonságot a Termékek megtekintése értékre.
6. ábra: HyperLinkField hozzáadása a Categories GridView-hoz
Az ObjectDataSource létrehozása és a GridView mezőinek testreszabása után a két vezérlő deklaratív korrektúra a következőképpen fog kinézni:
<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>
A 7. ábra Default.aspx böngészőn keresztül történő megtekintés során jelenik meg. A kategória "Termékek megtekintése" hivatkozásra kattintva a(z) ProductsByCategory.aspx?CategoryID=categoryID oldalra jut, amelyet a 3. lépésben fogunk felépíteni.
7. ábra: Minden kategória listázva van a termékek megtekintése hivatkozással együtt (ide kattintva megtekintheti a teljes méretű képet)
3. lépés: A kijelölt kategória termékeinek listázása
Nyissa meg a ProductsByCategory.aspx lapot, és adjon hozzá egy GridView nevet.ProductsByCategory Az intelligens címkéből kösse a GridView-t egy új ObjectDataSource nevű ProductsByCategoryDataSourceobjektumhoz. Konfigurálja az ObjectDataSource-t az ProductsBLL osztály s GetProductsByCategoryID(categoryID) metódusának használatára, és állítsa a legördülő listákat (None) értékre az UPDATE, INSERT és DELETE lapon.
8. ábra: Az osztály módszerének ProductsBLL használata GetProductsByCategoryID(categoryID) (kattintson ide a teljes méretű kép megtekintéséhez)
Az Adatforrás konfigurálása varázsló utolsó lépése a categoryID paraméterforrásának megadását kéri. Mivel ezek az adatok a lekérdezési mezőn CategoryIDkeresztül kerülnek továbbításra, válassza a QueryString lehetőséget a legördülő listából, és írja be a CategoryID értéket a QueryStringField szövegmezőbe a 9. ábrán látható módon. A varázsló befejezéséhez kattintson a Befejezés gombra.
9. ábra: A CategoryID paraméter lekérdezési mezőjének használata (ide kattintva megtekintheti a teljes méretű képet)
A varázsló befejezése után a Visual Studio hozzáadja a megfelelő BoundFields és egy CheckBoxField mezőt a GridView-hoz a termék adatmezőihez. Tartsa meg csak a ProductName, UnitPrice, és SupplierName BoundFields, a többit távolítsa el. Testreszabja ennek a három BoundFields HeaderText tulajdonságnak a megjelenítését, hogy a termék, az ár és a szállító jelenjen meg. Formázza a UnitPrice BoundFieldet pénznemként.
Ezután vegyen fel egy HyperLinkFieldet, és helyezze át a bal szélső pozícióba. Állítsa be a Text tulajdonságát a Részletek megtekintése értékre, a DataNavigateUrlFields tulajdonságát ProductID, és a DataNavigateUrlFormatString tulajdonságát ~/SiteMapProvider/ProductDetails.aspx?ProductID={0} értékre.
10. ábra: Nézet részleteinek hozzáadása HyperLinkField, amely a következőre mutat: ProductDetails.aspx
A testreszabások elvégzése után a GridView és az ObjectDataSource deklaratív korrektúrája a következőhöz hasonló:
<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>
Térjen vissza a Default.aspx megtekintéséhez egy böngészőben, és kattintson az Italok termékek megtekintése linkre.
ProductsByCategory.aspx?CategoryID=1Ekkor megjelenik a Northwind-adatbázisban az Italok kategóriához tartozó termékek neve, ára és szállítója (lásd a 11. ábrát). Nyugodtan tovább bővítheti ezt a lapot, hogy tartalmazzon egy hivatkozást, amellyel visszajuttathatja a felhasználókat a kategórialistalapra (Default.aspx) és egy DetailsView vagy FormView vezérlőre, amely megjeleníti a kiválasztott kategória nevét és leírását.
11. ábra: Megjelennek az italok nevei, árai és szállítói (ide kattintva megtekintheti a teljes méretű képet)
4. lépés: Termék részleteinek megjelenítése
Az utolsó oldal ProductDetails.aspxmegjeleníti a kiválasztott termékek részleteit. Nyissa meg ProductDetails.aspx, és húzza a DetailsView-t az eszközkészletből a Tervezőre. Állítsa be a DetailsView ID tulajdonságát ProductInfo értékre, és törölje a Height és Width tulajdonságok értékeit. Az intelligens címkéről csatolja a DetailsView-t egy új, ProductDataSource nevű ObjectDataSource-hoz, és konfigurálja úgy, hogy az ProductsBLL osztály GetProductByProductID(productID) metódusából kérje le az adatokat. A 2. és a 3. lépésben létrehozott korábbi weblapokhoz hasonlóan állítsa a legördülő listákat az UPDATE, INSERT és DELETE füleken (Nincs) értékre.
12. ábra: Az ObjectDataSource konfigurálása a GetProductByProductID(productID) metódus használatára (kattintson ide a teljes méretű kép megtekintéséhez)
Az Adatforrás konfigurálása varázsló utolsó lépése kéri a productID paraméter forrását. Mivel ezek az adatok a lekérdezési mezőn ProductIDkeresztül érkeznek, állítsa a legördülő listát QueryStringre, a QueryStringField szövegmezőt pedig ProductID értékre. Végül kattintson a Befejezés gombra a varázsló befejezéséhez.
13. ábra: Konfigurálja a productID paramétert úgy, hogy lekérje az értékét a ProductID lekérdezési mezőből (kattintson ide a teljes méretű kép megtekintéséhez)
Az Adatforrás konfigurálása varázsló befejezése után a Visual Studio létrehozza a megfelelő BoundFields és egy CheckBoxField mezőket a Termékadatmezők DetailsView elemében. Távolítsa el a ProductID, SupplierID, és CategoryID BoundFields mezőket, és konfigurálja a fennmaradó mezőket a megfelelőnek látja. Néhány esztétikai konfiguráció után a DetailsView és az ObjectDataSource deklaratív korrektúra az alábbihoz hasonlóan nézett ki:
<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>
A lap teszteléséhez térjen vissza Default.aspx , és kattintson a Italok kategória Termékek megtekintése parancsára. Az italtermékek listájában kattintson a Chai Tea részletek hivatkozására. Ez elviszi a ProductDetails.aspx?ProductID=1-ra, amely bemutatja a chai teát részleteit (lásd a 14. ábrát).
14. ábra: A Chai Tea szállítója, kategória, ár és egyéb információk jelennek meg (Kattintson ide a teljes méretű kép megtekintéséhez)
5. lépés: A webhelytérkép-szolgáltató belső működésének ismertetése
A webhelytérkép a webkiszolgáló memóriájában hierarchiát alkotó példányok gyűjteményeként SiteMapNode jelenik meg. Pontosan egy gyökérnek kell lennie, minden nem gyökércsomópontnak pontosan egy szülőcsomópontot kell tartalmaznia, és minden csomópontnak tetszőleges számú gyermeknek kell lennie. Minden SiteMapNode objektum egy szakaszt jelöl a webhely struktúrájában; ezek a szakaszok gyakran rendelkeznek egy megfelelő weblaptal. Ennek következtében az SiteMapNode osztály olyan tulajdonságokkal rendelkezik, mint Titlea , Urlés Description, amelyek információt nyújtanak az általuk képviselt szakaszról SiteMapNode . Van egy Key tulajdonság is, amely egyedileg azonosítja az egyes SiteMapNode a hierarchiában, valamint a hierarchia létrehozásához használt tulajdonságokat, mint például a ChildNodes, ParentNode, NextSibling, PreviousSibling, és így tovább.
A 15. ábra az 1. ábrán látható általános helytérkép-struktúrát mutatja be, de a megvalósítás részletei részletesebben körvonalazottak.
15. ábra: Mindegyikhez SiteMapNode hasonló tulajdonságok, példáulTitle, UrlKeyés így tovább (kattintson ide a teljes méretű kép megtekintéséhez)
A helytérkép aSiteMap névtér osztályán System.Webkeresztül érhető el. Ez az osztálytulajdonság RootNode visszaadja a webhelytérkép gyökérpéldányát SiteMapNode ; CurrentNode visszaadja azt a SiteMapNode tulajdonságot, amelynek Url a tulajdonsága megegyezik az aktuálisan kért oldal URL-címével. Ezt az osztályt ASP.NET 2.0-s navigációs webvezérlők belsőleg használják.
SiteMap Az osztály tulajdonságainak elérésekor szerializálnia kell a helytérkép szerkezetét valamilyen állandó adathordozóról a memóriába. A helytérkép szerializálási logikája azonban nincs keményen beágyazva az SiteMap osztályba. Futásidőben az SiteMap osztály határozza meg, hogy melyik helyleképezési szolgáltatót használja a szerializáláshoz. Alapértelmezés szerint a rendszer az XmlSiteMapProvider osztályt használja, amely egy megfelelően formázott XML-fájlból olvassa be a helytérkép struktúráját. Egy kis munkával azonban létrehozhatjuk saját egyéni webhelytérkép-szolgáltatónkat.
Minden helytérkép-szolgáltatónak az SiteMapProvider osztályból kell származnia, amely tartalmazza a helytérkép-szolgáltatókhoz szükséges alapvető módszereket és tulajdonságokat, de kihagyja a megvalósítás számos részletét. A második osztály kiterjeszti StaticSiteMapProvideraz SiteMapProvider osztályt, és a szükséges funkciók robusztusabb megvalósítását tartalmazza. Belsőleg a StaticSiteMapProvider a SiteMapNode webhelytérkép példányait egy Hashtable tárolja, és olyan metódusokat kínál, mint a AddNode(child, parent), RemoveNode(siteMapNode), és Clear(), amelyek SiteMapNode elemeket adnak hozzá és távolítanak el a belső Hashtable-ből.
XmlSiteMapProvider
StaticSiteMapProviderszármazik.
Ha olyan egyéni webhelytérkép-szolgáltatót hoz létre, amely kiterjed StaticSiteMapProvider, két absztrakt metódust kell felül bírálni: BuildSiteMap és GetRootNodeCore.
BuildSiteMap, ahogy a neve is mutatja, felelős a helytérkép szerkezetének az állandó tárolóból való betöltéséért és a memóriában való felépítéséért.
GetRootNodeCore visszaadja a gyökércsomópontot a helytérképen.
Ahhoz, hogy egy webalkalmazás használhassa a webhelytérkép-szolgáltatót, regisztrálnia kell az alkalmazás konfigurációjában. Alapértelmezés szerint az XmlSiteMapProvider osztály a névvel AspNetXmlSiteMapProvidervan regisztrálva. További webhelytérkép-szolgáltatók regisztrálásához adja hozzá a következő jelölést Web.config:
<configuration>
<system.web>
...
<siteMap defaultProvider="defaultProviderName">
<providers>
<add name="name" type="type" />
</providers>
</siteMap>
</system.web>
</configuration>
A névérték egy ember által olvasható nevet rendel a szolgáltatóhoz, míg a típus a webhelytérkép-szolgáltató teljes típusnevét adja meg. Az egyéni webhelytérkép-szolgáltató létrehozása után a 7. lépésben megismerjük a név - és típusértékek konkrét értékeit.
A webhelytérkép szolgáltatói osztálya az első alkalommal lesz példányosítva az osztályból SiteMap , és a webalkalmazás teljes élettartama alatt a memóriában marad. Mivel a webhelytérkép-szolgáltatónak csak egy példánya hívható meg több egyidejű webhelylátogatótól, elengedhetetlen, hogy a szolgáltató metódusai szálbiztosak legyenek.
Teljesítmény- és méretezhetőségi okokból fontos, hogy gyorsítótárazzuk a memóriabeli helytérkép struktúráját, és ezt a gyorsítótárazott struktúrát adjuk vissza, ahelyett, hogy minden alkalommal újra létrehoznánk, amikor a BuildSiteMap metódust meghívják.
BuildSiteMap a lapon használt navigációs vezérlőktől és a webhelytérkép szerkezetének mélységétől függően felhasználónként többször is meghívható. Mindenesetre, ha nem gyorsítótárazzuk a helytérkép struktúráját BuildSiteMap , akkor minden egyes meghíváskor újra le kell kérnünk a termék- és kategóriaadatokat az architektúrából (ami lekérdezést eredményezne az adatbázisba). Ahogy az előző gyorsítótárazási oktatóanyagokban is tárgyaltuk, a gyorsítótárazott adatok elavulttá válhatnak. Ennek leküzdéséhez idő- vagy SQL Cache-alapú függőségalapú lejáratokat használhatunk.
Megjegyzés:
A webhelytérkép-szolgáltató opcionálisan felülbírálhatja a metódustInitialize.
Initialize akkor hívódik meg, amikor a helytérkép-szolgáltató első példányosítása történik, és ehhez adjuk át a szolgáltatóhoz rendelt egyéni attribútumokat a Web.config elemben<add>: <add name="name" type="type" customAttribute="value" />. Akkor hasznos, ha lehetővé szeretné tenni, hogy egy lapfejlesztő különböző webhelytérkép-szolgáltatóhoz kapcsolódó beállításokat adjon meg anélkül, hogy módosítania kellene a szolgáltató kódját. Ha például közvetlenül az adatbázisból olvasnánk ki a kategória- és termékadatokat az architektúra helyett, akkor a lap fejlesztője valószínűleg az adatbázis-kapcsolati sztringet Web.config szeretné megadni a szolgáltató kódjában való rögzítés helyett. A 6. lépésben buildelt egyéni webhelyleképezési szolgáltató nem bírálja felül ezt a Initialize módszert. A módszer használatára Initializepéldaként tekintse meg Jeff Prosisewebhelytérképek tárolását az SQL Serverben című cikkben.
6. lépés: Az egyéni webhelytérkép-szolgáltató létrehozása
Ha olyan egyéni webhelytérkép-szolgáltatót szeretne létrehozni, amely a Northwind-adatbázisban lévő kategóriákból és termékekből hozza létre a webhelytérképet, létre kell hoznunk egy olyan osztályt, amely kiterjeszthető StaticSiteMapProvider. Az 1. lépésben arra kértem, hogy vegyen fel egy CustomProviders mappát a App_Code mappába – adjon hozzá egy új osztályt ehhez a mappához.NorthwindSiteMapProvider Adja hozzá a következő kódot az NorthwindSiteMapProvider osztályhoz:
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?;
}
}
}
Kezdjük az osztály s BuildSiteMap metódusának feltárásával, amely egy lock utasítással kezdődik. Az lock utasítás egyszerre csak egy szál beírását teszi lehetővé, ezáltal szerializálva a kódhoz való hozzáférést, és megakadályozza, hogy két egyidejű szál egymás lábán lépkedjen.
Az osztályszintű SiteMapNode változó root a helytérkép szerkezetének gyorsítótárazására szolgál. Amikor a helytérkép először készül el, vagy először azután, hogy a mögöttes adatokat módosították, akkor root lesz null, és a helytérkép szerkezete felépül. A helytérkép gyökércsomópontja az építési folyamat során hozzá van rendelve root-hoz, hogy a metódus következő meghívásakor root ne legyen null. Következésképpen, amíg root nem null, a helytérkép struktúrája vissza lesz adva a hívónak anélkül, hogy azt újra létre kellene hozni.
Gyökér esetén nulla webhelytérkép struktúrája a termék- és kategóriaadatokból jön létre. A webhelytérkép a SiteMapNode példányok létrehozásával jön létre, majd a hierarchiát az StaticSiteMapProvider osztály AddNode metódusának hívásával alakítjuk ki.
AddNode elvégzi a belső könyvelést, különféle SiteMapNode példányokat tárolva egy Hashtable-ben. Mielőtt elkezdenénk felépíteni a hierarchiát, a Clear metódus meghívásával kezdjük, amely törli az elemeket a belső Hashtable-ből. Ezután az ProductsBLL osztály s GetProducts metódusa és az eredmény ProductsDataTable helyi változókban lesz tárolva.
A helytérkép felépítése a gyökércsomópont létrehozásával és a hozzá való hozzárendeléssel rootkezdődik. Az itt és az egész SiteMapNode során használt a következő információkat kapja:
- Hivatkozás a webhelytérkép-szolgáltatóra (
this). - Az
SiteMapNodesKey. Ennek a kötelező értéknek egyedinek kell lennie az egyesSiteMapNode. - Az
SiteMapNodesUrl.Urlnem kötelező, de ha meg van adva, mindenSiteMapNodesUrlértéknek egyedinek kell lennie. - Az
SiteMapNodesTitle, amely szükséges.
A AddNode(root) metódushívás gyökérként hozzáadja a SiteMapNoderoot webhelytérképhez. A következő lépésben mindegyik ProductRowProductsDataTable számba lesz sorolva. Ha már létezik egy SiteMapNode az aktuális termékkategóriához, a rendszer hivatkozik rá. "Ellenkező esetben a rendszer létrehoz egy új SiteMapNode elemet a kategóriához, és hozzáadja azt a SiteMapNode``root gyermekéhez a AddNode(categoryNode, root) metódushíváson keresztül." Miután megtalálták vagy létrehozták a megfelelő SiteMapNode kategóriát, egy SiteMapNode jön létre az aktuális termékhez, amelyet a kategória SiteMapNode gyermekeként adnak hozzá AddNode(productNode, categoryNode) segítségével. Vegye figyelembe, hogy a kategória SiteMapNodeUrl tulajdonságértéke ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID, míg a termék SiteMapNodeUrl tulajdonsága ~/SiteMapNode/ProductDetails.aspx?ProductID=productID-ként van hozzárendelve.
Megjegyzés:
Azok a termékek, amelyek adatbázis-értékkel NULL rendelkeznek, CategoryID egy olyan kategóriába SiteMapNode vannak csoportosítva, amelynek Title tulajdonsága Nincs, és amelynek Url tulajdonsága üres karakterláncra lett állítva. Úgy döntöttem, hogy egy üres karakterláncot állítok be Url, mivel az ProductBLL osztály GetProductsByCategory(categoryID) metódusa jelenleg nem képes visszaadni azokat a termékeket, amelyek rendelkeznek NULLCategoryID értékkel. Azt is be akartam mutatni, hogyan jelenítik meg a navigációs vezérlők a SiteMapNode elemet, amely nem tartalmaz értéket a Url tulajdonsága számára. Arra buzdítom önt, hogy bővítse ki ezt az oktatóanyagot úgy, hogy a None SiteMapNode s Url tulajdonság a ProductsByCategory.aspx-ra mutasson, de csak azokat a termékeket jelenítse meg, amelyek NULLCategoryID értékkel rendelkeznek.
A helytérkép létrehozása után a rendszer egy tetszőleges objektumot ad hozzá az adatgyorsítótárhoz egy Categories objektumon keresztüli SQL Cache-függőség használatával a Products és AggregateCacheDependency táblákon keresztül. Az SQL Cache-függőségek használatát az előző oktatóanyag, az SQL Cache-függőségek használata című oktatóanyagban ismertettük. Az egyéni webhelytérkép-szolgáltató azonban az adatgyorsítótár Insert módszerének egy túlterhelt változatát használja, amelyet még nem vizsgáltunk meg. Ez a túlterhelés végső bemeneti paraméterként fogad el egy delegáltat, aki akkor lesz meghívva, amikor az objektumot eltávolítják a gyorsítótárból. Pontosabban egy új CacheItemRemovedCallback delegáltat adunk át, amely az OnSiteMapChanged osztályban részletesebben definiált metódusra NorthwindSiteMapProvider mutat.
Megjegyzés:
A helytérkép memóriabeli ábrázolását az osztályszintű változó root gyorsítótárazza. Mivel az egyéni helyleképezési szolgáltató osztálynak csak egy példánya van, és mivel a példány meg van osztva a webalkalmazás összes szála között, ez az osztályváltozó gyorsítótárként szolgál. A BuildSiteMap metódus az adatgyorsítótárat is használja, azonban csak eszközként, hogy értesítést kapjon, ha a mögöttes adatbázis adatai a Categories vagy Products táblákban megváltoznak. Vegye figyelembe, hogy az adatgyorsítótárba helyezett érték csak az aktuális dátum és idő. A webhelytérkép tényleges adatai nem kerülnek az adatgyorsítótárba.
A BuildSiteMap metódus a helytérkép gyökércsomópontjának visszaadásával fejeződik be.
A fennmaradó módszerek meglehetősen egyszerűek.
GetRootNodeCore felelős a gyökércsomópont visszaadásáért. Mivel BuildSiteMap a gyökérértéket adja vissza, GetRootNodeCore egyszerűen BuildSiteMap visszatérési értékét adja vissza. A OnSiteMapChanged metódus visszaállítja root a null értékre, amikor a gyorsítótárelem eltávolításra kerül. Ha a gyökér vissza van állítva null, akkor amikor legközelebb a BuildSiteMap meghívásra kerül, a webhelytérkép struktúrája újra épül. Végül a tulajdonság az CachedDate adatgyorsítótárban tárolt dátum- és időértéket adja vissza, ha létezik ilyen érték. Ezt a tulajdonságot a lapfejlesztők használhatják annak meghatározására, hogy a webhelytérkép adatai mikor gyorsítótáraztak utoljára.
7. lépés: A regisztrálásaNorthwindSiteMapProvider
Ahhoz, hogy webalkalmazásunk a 6. lépésben létrehozott webhelytérkép-szolgáltatót használhassa, regisztrálnunk kell azt a NorthwindSiteMapProvider szekcióban a <siteMap>. Pontosabban, adja hozzá a következő jelölést a <system.web> elemben Web.config:
<siteMap defaultProvider="AspNetXmlSiteMapProvider">
<providers>
<add name="Northwind" type="NorthwindSiteMapProvider" />
</providers>
</siteMap>
Ez a jelölés két dolgot tesz: először is jelzi, hogy a beépített AspNetXmlSiteMapProvider az alapértelmezett webhelytérkép-szolgáltató; másodszor regisztrálja a 6. lépésben létrehozott egyéni webhelytérkép-szolgáltatót a Northwind emberbarát néven.
Megjegyzés:
Az alkalmazás mappájában App_Code található helytérkép-szolgáltatók esetében az type attribútum értéke egyszerűen az osztály neve. Másik lehetőségként az egyéni webhelytérkép-szolgáltatót létrehozhatták volna egy külön osztálykönyvtár projektben, az összeállított assembly pedig a webalkalmazás /Bin könyvtárába került. Ebben az esetben az attribútum értéke type.ClassName, AssemblyName.
A frissítés Web.configután szánjon egy kis időt a böngészőben található oktatóanyagok bármelyik oldalának megtekintésére. Vegye figyelembe, hogy a bal oldali navigációs felület továbbra is megjeleníti a Web.sitemap-ben definiált szakaszokat és oktatóanyagokat. Ez azért van így, mert AspNetXmlSiteMapProvider alapértelmezett szolgáltatóként hagytuk meg. Ahhoz, hogy létrehozhassunk egy navigációs felhasználói felületi elemet, amely a NorthwindSiteMapProviderkövetkezőt használja, explicit módon meg kell határoznunk, hogy a Northwind webhelytérkép-szolgáltatót kell használni. Ezt a 8. lépésben fogjuk látni.
8. lépés: Webhelytérkép adatainak megjelenítése az egyéni webhelytérkép-szolgáltató használatával
Az egyéni webhelytérkép-szolgáltató létrehozása és regisztrálása Web.configután készen állunk navigációs vezérlők hozzáadására a Default.aspxmappában lévő ProductsByCategory.aspx , ProductDetails.aspxés SiteMapProvider lapokhoz. Először nyissa meg a Default.aspx oldalt, majd húzzon egy SiteMapPath elemet az Eszközkészletből a Tervezőre. A SiteMapPath vezérlő az eszközkészlet navigációs szakaszában található.
16. ábra: SiteMapPath hozzáadása (Default.aspxide kattintva megtekintheti a teljes méretű képet)
A SiteMapPath vezérlő egy morzsamenüt jelenít meg, amely az aktuális oldal helyét jelzi a webhelytérképen belül. A Mesterlapok és a Webhelynavigáció oktatóanyagban hozzáadtunk egy SiteMapPath-t a mesterlap tetejére.
Szánjon egy kis időt a lap megtekintésére egy böngészőben. A 16. ábrán hozzáadott SiteMapPath az alapértelmezett helytérkép-szolgáltatót használja, amelyből Web.sitemaplekéri az adatokat. Ezért a kenyérmorzsa így néz ki: Kezdőlap > Webhelytérkép testreszabása, ugyanúgy, mint a jobb felső sarokban található kenyérmorzsa.
17. ábra: A Breadcrumb az alapértelmezett helytérkép-szolgáltatót használja (ide kattintva megtekintheti a teljes méretű képet)
Ha a 16. ábrán a SiteMapPathot szeretné hozzáadni, használja a 6. lépésben létrehozott egyéni webhelytérkép-szolgáltatót, állítsa a tulajdonságátSiteMapProvider Northwindre, a névre, amelyet a NorthwindSiteMapProvider 6. lépésben Web.configrendeltünk hozzá. Sajnos a Tervező továbbra is az alapértelmezett webhelytérkép-szolgáltatót használja, de ha a tulajdonság módosítása után böngészőben látogatja meg az oldalt, láthatja, hogy a morzsa már az egyéni webhelytérkép-szolgáltatót használja.
18. ábra: A Breadcrumb most az egyéni webhelytérkép-szolgáltatót NorthwindSiteMapProvider használja (ide kattintva megtekintheti a teljes méretű képet)
A SiteMapPath vezérlő egy funkcionálisabb felhasználói felületet jelenít meg a ProductsByCategory.aspx és ProductDetails.aspx oldalakban. Adjon hozzá egy SiteMapPath-t ezekhez a lapokhoz, és állítsa be a SiteMapProvider tulajdonságot mindkettőben a Northwindre. Kattintson Default.aspx az Italok megtekintése hivatkozásra, majd a Chai Tea részleteinek megtekintése hivatkozásra. Ahogy a 19. ábrán látható, a zsemle az aktuális webhelytérkép szakaszt (Chai Tea) és elődeit tartalmazza: Italok és minden kategória.
19. ábra: A Breadcrumb most az egyéni webhelytérkép-szolgáltatót NorthwindSiteMapProvider használja (ide kattintva megtekintheti a teljes méretű képet)
A SiteMapPath mellett más navigációs felhasználói felületi elemek is használhatók, például a Menü és a TreeView vezérlők. Az oktatóanyag letöltésében található Default.aspx, ProductsByCategory.aspx és ProductDetails.aspx oldalak például mind tartalmazzák a Menü vezérlőelemeket (lásd a 20. ábrát).
ASP.NET 2.0 kifinomult webhely-navigációs funkciói és az ASP.NET 2.0 gyorsútmutatókWebhely-navigációs vezérlők használata szakasza részletesebb betekintést nyújt az ASP.NET 2.0 navigációs vezérlőibe és webhelytérkép-rendszerébe.
20. ábra: A menüvezérlő felsorolja az egyes kategóriákat és termékeket (ide kattintva megtekintheti a teljes méretű képet)
Ahogy az oktatóanyag korábbi részében is említettük, a webhelytérkép struktúrája programozott módon érhető el az SiteMap osztályon keresztül. Az alábbi kód az alapértelmezett szolgáltató gyökerét SiteMapNode adja vissza:
SiteMapNode root = SiteMap.RootNode;
Mivel az AspNetXmlSiteMapProvider alkalmazás alapértelmezett szolgáltatója, a fenti kód a megadott gyökércsomópontot Web.sitemapadja vissza. Ha nem az alapértelmezett webhelytérkép-szolgáltatóra szeretne hivatkozni, használja az SiteMap osztály s tulajdonságátProviders a következőképpen:
SiteMapNode root = SiteMap.Providers["name"].RootNode;
Ahol a név az egyéni webhelytérkép-szolgáltató neve ( Northwind, webalkalmazásunk esetében).
A webhelytérkép-szolgáltatóhoz tartozó tag eléréséhez használja SiteMap.Providers["name"]-t a szolgáltatópéldány lekéréséhez, majd alakítsa át a megfelelő típusra. Ha például egy ASP.NET lapon szeretné megjeleníteni az NorthwindSiteMapProvider s CachedDate tulajdonságot, használja a következő kódot:
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!";
}
Megjegyzés:
Mindenképpen tesztelje az SQL Cache függőségi funkcióját. Miután felkereste a Default.aspx, valamint ProductsByCategory.aspx és ProductDetails.aspx oldalakat, keresse meg a Szerkesztés, Beszúrás és Törlés szakasz egyik oktatóanyagát, és szerkessze egy kategória vagy termék nevét. Ezután térjen vissza a mappa egyik lapjára SiteMapProvider . Feltételezve, hogy elegendő idő telt el ahhoz, hogy a lekérdezési mechanizmus megfigyelje a mögöttes adatbázis változását, a helytérképet frissíteni kell az új termék vagy kategória nevének megjelenítéséhez.
Összefoglalás
ASP.NET 2.0-s webhelytérkép-funkciók közé tartozik egy SiteMap osztály, számos beépített navigációs webvezérlő és egy alapértelmezett helytérkép-szolgáltató, amely azt várja, hogy a webhelytérkép adatai megmaradjanak egy XML-fájlban. Ahhoz, hogy más forrásból, például egy adatbázisból, az alkalmazás architektúrájából vagy egy távoli webszolgáltatásból származó webhelytérkép-információkat használhassunk, létre kell hoznunk egy egyéni webhelytérkép-szolgáltatót. Ez magában foglalja egy olyan osztály létrehozását, amely közvetlenül vagy közvetve származik az SiteMapProvider osztályból.
Ebben az oktatóanyagban bemutattuk, hogyan hozhat létre egyéni webhelytérkép-szolgáltatót, amely a webhelytérképet az alkalmazásarchitektúrából törölt termék- és kategóriainformációk alapján hozta létre. A szolgáltató kiterjesztette az StaticSiteMapProvider osztályt, és létrehozott egy BuildSiteMap metódust, amely lekérte az adatokat, létrehozta a helyleképezési hierarchiát, és gyorsítótárazza az eredményként kapott struktúrát egy osztályszintű változóban. Gyorsítótár-függőséget használtunk egy visszahívó függvénnyel, hogy érvénytelenítsük a gyorsítótárazott struktúrát, amikor az alapul szolgáló Categories vagy Products adatok módosulnak.
Boldog programozást!
További olvasás
Az oktatóanyagban tárgyalt témakörökről az alábbi forrásokban talál további információt:
- Helytérképek tárolása az SQL Serverben és az SQL-helytérkép-szolgáltató, amire vártál
- A Szolgáltatói eszközkészlet
- ASP.NET 2.0 kifinomult webhelynavigációs funkciói
Tudnivalók a szerzőről
Scott Mitchell, hét ASP/ASP.NET-könyv szerzője és a 4GuysFromRolla.com alapítója, 1998 óta dolgozik a Microsoft webtechnológiáival. Scott független tanácsadóként, edzőként és íróként dolgozik. Legújabb könyve Sams Tanuld meg ASP.NET 2.0 24 óra alatt. Ő itt elérhető mitchell@4GuysFromRolla.com.
Külön köszönet
Ezt az oktatóanyag-sorozatot sok hasznos véleményező áttekintette. Az oktatóanyag fő véleményezői Dave Gardner, Zack Jones, Teresa Murphy és Bernadette Leigh voltak. Szeretné áttekinteni a közelgő MSDN-cikkeimet? Ha igen, írj egy sort a mitchell@4GuysFromRolla.com-ra.