Udostępnij za pośrednictwem


Tworzenie niestandardowego dostawcy map witryn opartych na bazie danych (C#)

Autor: Scott Mitchell

Pobierz plik PDF

Domyślny dostawca mapy witryny w ASP.NET 2.0 pobiera dane ze statycznego pliku XML. Chociaż dostawca oparty na formacie XML jest odpowiedni dla wielu małych i średnich witryn sieci Web, większe aplikacje internetowe wymagają bardziej dynamicznej mapy witryny. W tym samouczku utworzymy niestandardowego dostawcę mapy witryny, który pobiera dane z warstwy logiki biznesowej, który z kolei pobiera dane z bazy danych.

Wprowadzenie

funkcja mapy witryny ASP.NET 2.0 umożliwia deweloperowi strony zdefiniowanie mapy witryny aplikacji internetowej na nośniku trwałym, na przykład w pliku XML. Po zdefiniowaniu można uzyskać dostęp do danych mapy witryny programowo za pośrednictwem klasy w System.Web przestrzeni nazw lub za pomocą SiteMap różnych kontrolek nawigacji sieci Web, takich jak SiteMapPath, Menu i TreeView. System mapy lokacji używa modelu dostawcy, aby można było utworzyć i podłączyć do aplikacji internetowej różne implementacje serializacji mapy witryny. Domyślny dostawca mapy witryny dostarczany z ASP.NET 2.0 utrzymuje strukturę mapy witryny w pliku XML. W samouczku Dotyczącym stron wzorcowych i nawigacji witryny utworzyliśmy plik o nazwie Web.sitemap zawierający tę strukturę i zaktualizowaliśmy kod XML przy użyciu każdej nowej sekcji samouczka.

Domyślny dostawca mapy witryny opartej na formacie XML sprawdza się, jeśli struktura mapy witryny jest dość statyczna, na przykład w przypadku tych samouczków. W wielu scenariuszach wymagana jest jednak bardziej dynamiczna mapa witryny. Rozważ mapę witryny pokazaną na rysunku 1, gdzie każda kategoria i produkt są wyświetlane jako sekcje w strukturze witryny internetowej. Na tej mapie witryny odwiedź stronę internetową odpowiadającą węzłowi głównemu może wyświetlić listę wszystkich kategorii, podczas gdy odwiedzanie określonej strony sieci Web kategorii spowoduje wyświetlenie tej kategorii produktów i wyświetlenie określonej strony sieci Web produktu.

Kategorie i produkty makijaż struktury mapy witryny

Rysunek 1. Kategorie i produkty Makijaż struktura mapy witryny (kliknij, aby wyświetlić obraz pełnowymiarowy)

Chociaż ta struktura oparta na kategorii i produktach może być zakodowana w Web.sitemap pliku, plik musi zostać zaktualizowany za każdym razem, gdy kategoria lub produkt został dodany, usunięty lub zmieniony. W związku z tym konserwacja mapy lokacji byłaby znacznie uproszczona, jeśli jej struktura została pobrana z bazy danych lub, najlepiej, z warstwy logiki biznesowej architektury aplikacji. Dzięki temu, w miarę dodawania produktów i kategorii, zmiany nazwy lub usunięcia mapa witryny zostanie automatycznie zaktualizowana w celu odzwierciedlenia tych zmian.

Ponieważ ASP.NET serializacji mapy lokacji w wersji 2.0 jest zbudowana na szczycie modelu dostawcy, możemy utworzyć własnego niestandardowego dostawcę mapy witryny, który pobiera dane z alternatywnego magazynu danych, takiego jak baza danych lub architektura. W tym samouczku utworzymy dostawcę niestandardowego, który pobiera dane z usługi BLL. Zacznijmy!

Uwaga

Niestandardowy dostawca mapy witryny utworzony w tym samouczku jest ściśle powiązany z architekturą aplikacji i modelem danych. Jeff Prosise s Storing Site Maps in SQL Server and The SQL Site Map Provider You ve Was Was Waiting For articles examine a generalized approach to storing site map data in SQL Server .The SQL Site Map Provider You ve Was Waiting For articles examine a generalized approach to storing site map data in SQL Server .

Krok 1. Tworzenie niestandardowych stron sieci Web dostawcy map witryn

Zanim zaczniemy tworzyć niestandardowego dostawcę mapy witryny, najpierw dodajmy strony ASP.NET, których będziemy potrzebować w tym samouczku. Zacznij od dodania nowego folderu o nazwie SiteMapProvider. Następnie dodaj następujące strony ASP.NET do tego folderu, aby skojarzyć każdą stronę ze stroną wzorcową Site.master :

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

CustomProviders Dodaj również podfolder do App_Code folderu .

Dodawanie stron ASP.NET dla samouczków związanych z dostawcą mapy witryny

Rysunek 2. Dodawanie stron ASP.NET dla samouczków związanych z dostawcą mapy witryny

Ponieważ w tej sekcji znajduje się tylko jeden samouczek, nie musimy Default.aspx wyświetlać listy samouczków sekcji. Default.aspx Zamiast tego zostaną wyświetlone kategorie w kontrolce GridView. Zajmiemy się tym w kroku 2.

Następnie zaktualizuj element Web.sitemap , aby dołączyć odwołanie do Default.aspx strony. W szczególności dodaj następujący znacznik po buforowaniu <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 zaktualizowaniu Web.sitemapprogramu pośmiń chwilę, aby wyświetlić witrynę internetową samouczków za pośrednictwem przeglądarki. Menu po lewej stronie zawiera teraz element dla jedynego samouczka dostawcy mapy witryny.

Mapa witryny zawiera teraz wpis dla samouczka dostawcy mapy witryny

Rysunek 3. Mapa witryny zawiera teraz wpis dla samouczka dostawcy mapy witryny

Głównym celem tego samouczka jest zilustrowanie tworzenia niestandardowego dostawcy mapy witryny i konfigurowania aplikacji internetowej do korzystania z tego dostawcy. W szczególności utworzymy dostawcę, który zwraca mapę witryny zawierającą węzeł główny wraz z węzłem dla każdej kategorii i produktu, jak pokazano na rysunku 1. Ogólnie rzecz biorąc, każdy węzeł na mapie witryny może określać adres URL. Dla naszej mapy witryny adres URL węzła głównego będzie ~/SiteMapProvider/Default.aspxmieć wartość , która będzie zawierać listę wszystkich kategorii w bazie danych. Każdy węzeł kategorii na mapie witryny będzie miał adres URL wskazujący element , który będzie zawierać ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryIDlistę wszystkich produktów w określonym identyfikatorze categoryID. Na koniec każdy węzeł mapy witryny produktu wskaże ~/SiteMapProvider/ProductDetails.aspx?ProductID=productIDelement , który wyświetli szczegóły określonego produktu.

Aby rozpocząć, musimy utworzyć Default.aspxstrony , ProductsByCategory.aspxi ProductDetails.aspx . Te strony są wykonywane odpowiednio w krokach 2, 3 i 4. Ponieważ wepchnięcie tego samouczka dotyczy dostawców mapy witryny, a od poprzednich samouczków omówiliśmy tworzenie tego rodzaju wielostronicowych raportów wzorcowych/szczegółowych, spieszymy się przez kroki od 2 do 4. Jeśli potrzebujesz odświeżenia podczas tworzenia raportów wzorca/szczegółów obejmujących wiele stron, zapoznaj się z samouczkiem Filtrowanie wzorca/szczegółów na dwóch stronach .

Krok 2. Wyświetlanie listy kategorii

Default.aspx Otwórz stronę w folderze SiteMapProvider i przeciągnij kontrolkę GridView z przybornika do projektanta, ustawiając jej ID wartość na Categories. Z tagu inteligentnego GridView powiąż go z nowym obiektem ObjectDataSource o nazwie CategoriesDataSource i skonfiguruj go tak, aby pobierał swoje dane przy użyciu CategoriesBLL metody klasy s GetCategories . Ponieważ ten element GridView wyświetla tylko kategorie i nie udostępnia możliwości modyfikacji danych, ustaw listy rozwijane na kartach UPDATE, INSERT i DELETE na wartość (Brak).

Konfigurowanie obiektu ObjectDataSource w celu zwrócenia kategorii przy użyciu metody GetCategories

Rysunek 4. Konfigurowanie obiektu ObjectDataSource do zwracania kategorii przy użyciu GetCategories metody (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Ustaw listy rozwijane na kartach UPDATE, INSERT i DELETE na wartość (Brak)

Rysunek 5. Ustawianie list rozwijanych na kartach UPDATE, INSERT i DELETE na wartość (Brak) (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po ukończeniu pracy kreatora Konfigurowanie źródła danych program Visual Studio doda pole boundfield dla CategoryID, , CategoryNameDescription, NumberOfProductsi BrochurePath. Edytuj kontrolkę GridView, aby zawierała tylko pola CategoryName i i Description i zaktualizuj CategoryName właściwość BoundField na HeaderText Category .

Następnie dodaj pole HyperLinkField i umieść je tak, aby było to pole z lewej strony. DataNavigateUrlFields Ustaw właściwość na CategoryID , a DataNavigateUrlFormatString właściwość na ~/SiteMapProvider/ProductsByCategory.aspx?CategoryID={0}. Text Ustaw właściwość na Wyświetl produkty .

Dodawanie pola HyperLinkField do kontrolki GridView kategorii

Rysunek 6. Dodawanie pola HyperLinkField do kontrolki Categories GridView

Po utworzeniu obiektu ObjectDataSource i dostosowaniu pól kontrolki GridView znacznik deklaratywne będą wyglądać następująco:

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

Rysunek 7 przedstawia Default.aspx wyświetlanie w przeglądarce. Kliknięcie linku Wyświetl produkty kategorii spowoduje przejście do ProductsByCategory.aspx?CategoryID=categoryIDelementu , który utworzymy w kroku 3.

Każda kategoria jest wyświetlana wraz z linkiem Wyświetl produkty

Rysunek 7. Każda kategoria jest wyświetlana wraz z linkiem Wyświetl produkty (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 3. Wyświetlanie listy wybranych produktów kategorii

ProductsByCategory.aspx Otwórz stronę i dodaj kontrolkę GridView, nazewając ją ProductsByCategory. Z tagu inteligentnego powiąż element GridView z nowym obiektem ObjectDataSource o nazwie ProductsByCategoryDataSource. Skonfiguruj obiekt ObjectDataSource do używania ProductsBLL metody s GetProductsByCategoryID(categoryID) klasy i ustaw listy rozwijane na wartość (Brak) na kartach UPDATE, INSERT i DELETE.

Użyj metody GetProductsByCategoryID(categoryID) klasy ProductsBLL

Rysunek 8. Użycie ProductsBLL metody Klasy GetProductsByCategoryID(categoryID) (kliknij, aby wyświetlić obraz pełnowymiarowy)

Ostatni krok w kreatorze Konfigurowanie źródła danych wyświetla monit o podanie źródła parametrów dla categoryID. Ponieważ te informacje są przekazywane przez pole CategoryIDquerystring, wybierz pozycję QueryString z listy rozwijanej i wprowadź ciąg CategoryID w polu tekstowym QueryStringField, jak pokazano na rysunku 9. Kliknij przycisk Zakończ, aby zakończyć kreatora.

Użyj pola CategoryID Querystring dla parametru categoryID

Rysunek 9. Użyj pola querystring dla parametru CategoryID categoryID (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora program Visual Studio doda odpowiednie pola BoundFields i CheckBoxField do kontrolki GridView dla pól danych produktu. Usuń wszystkie elementy, ale ProductNamepola , UnitPricei SupplierName BoundFields. Dostosuj te trzy właściwości BoundFields HeaderText , aby odpowiednio odczytywać pozycje Produkt, Cena i Dostawca. Formatuj pole UnitPrice BoundField jako walutę.

Następnie dodaj pole HyperLinkField i przenieś je do lewej pozycji. Ustaw jej Text właściwość na Wyświetl szczegóły, jej DataNavigateUrlFields właściwość na ProductID, a jej DataNavigateUrlFormatString właściwość na ~/SiteMapProvider/ProductDetails.aspx?ProductID={0}.

Dodawanie pola HyperLinkField szczegółów widoku wskazującego na ProductDetails.aspx

Rysunek 10. Dodawanie pola HyperLinkField szczegółów widoku wskazującego na ProductDetails.aspx

Po wprowadzeniu tych dostosowań znaczniki deklaratywne gridView i ObjectDataSource powinny wyglądać podobnie do następujących:

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

Wróć do przeglądania Default.aspx za pośrednictwem przeglądarki i kliknij link Wyświetl produkty dla napojów. Spowoduje to wyświetlenie ProductsByCategory.aspx?CategoryID=1nazw, cen i dostawców produktów w bazie danych Northwind należących do kategorii Napoje (patrz Rysunek 11). Możesz dodatkowo ulepszyć tę stronę, aby dołączyć link umożliwiający zwrócenie użytkowników do strony listy kategorii (Default.aspx) oraz kontrolki DetailsView lub FormView, która wyświetla nazwę i opis wybranej kategorii.

Wyświetlane są nazwy, ceny i dostawcy napojów

Rysunek 11. Wyświetlane są nazwy napojów, ceny i dostawcy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 4. Wyświetlanie szczegółów produktu

Ostatnia strona , ProductDetails.aspxwyświetla szczegóły wybranych produktów. Otwórz ProductDetails.aspx element DetailsView z przybornika i przeciągnij go do projektanta. Ustaw właściwość DetailsView ID na ProductInfo i wyczyść jej Height wartości właściwości i Width . Na podstawie tagu inteligentnego powiąż element DetailsView z nowym obiektem ObjectDataSource o nazwie ProductDataSource, konfigurując obiekt ObjectDataSource w celu ściągnięcia danych z ProductsBLL metody klasy s GetProductByProductID(productID) . Podobnie jak w przypadku poprzednich stron internetowych utworzonych w krokach 2 i 3, ustaw listy rozwijane na kartach UPDATE, INSERT i DELETE na wartość (Brak).

Konfigurowanie obiektu ObjectDataSource do używania metody GetProductByProductID(productID)

Rysunek 12. Konfigurowanie obiektu ObjectDataSource do użycia GetProductByProductID(productID) metody (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W ostatnim kroku kreatora Konfigurowania źródła danych zostanie wyświetlony monit o podanie źródła parametru productID . Ponieważ te dane przechodzą przez pole ProductIDquerystring, ustaw listę rozwijaną na QueryString i Pole tekstowe QueryStringField na ProductID. Na koniec kliknij przycisk Zakończ, aby ukończyć pracę kreatora.

Konfigurowanie parametru productID w celu ściągnięcia jego wartości z pola ProductID Querystring

Rysunek 13. Konfigurowanie parametru productID w celu ściągnięcia jego wartości z ProductID pola Ciąg zapytania (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora Konfigurowanie źródła danych program Visual Studio utworzy odpowiednie pola BoundFields i CheckBoxField w obszarze DetailsView dla pól danych produktu. ProductIDUsuń pola , SupplierIDi CategoryID BoundFields i skonfiguruj pozostałe pola w miarę dopasowania. Po kilku konfiguracjach estetycznych moje znaczniki deklaratywne DetailsView i ObjectDataSource wyglądały następująco:

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

Aby przetestować tę stronę, wróć do Default.aspx i kliknij pozycję Wyświetl produkty dla kategorii Napoje. Na liście produktów napojów kliknij link Wyświetl szczegóły dla Chai Tea. Spowoduje to przejście do ProductDetails.aspx?ProductID=1elementu , w którym zostaną wyświetlone szczegóły Chai Tea (patrz Rysunek 14).

Chai Tea s Supplier, Category, Price i Other Information is Displayed (Dostawca, Kategoria, Cena i Inne informacje)

Rysunek 14. Wyświetlana jest pozycja Chai Tea s Supplier, Category, Price i Other Information (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 5. Zrozumienie wewnętrznego działania dostawcy mapy lokacji

Mapa witryny jest reprezentowana w pamięci serwera internetowego jako zbiór SiteMapNode wystąpień, które tworzą hierarchię. Musi istnieć dokładnie jeden katalog główny, wszystkie węzły inne niż główne muszą mieć dokładnie jeden węzeł nadrzędny, a wszystkie węzły mogą mieć dowolną liczbę elementów podrzędnych. Każdy SiteMapNode obiekt reprezentuje sekcję w strukturze witryny internetowej. Te sekcje często mają odpowiednią stronę internetową. SiteMapNode W związku z tym klasa ma właściwości takie jak Title, Urli Description, które zawierają informacje dotyczące sekcji reprezentowanej przez klasę SiteMapNode . Istnieje również Key właściwość, która jednoznacznie identyfikuje każdą SiteMapNode z nich w hierarchii, a także właściwości używane do ustanowienia tej hierarchii ChildNodes, , ParentNodeNextSibling, PreviousSiblingi tak dalej.

Rysunek 15 przedstawia ogólną strukturę mapy witryny na rysunku 1, ale szczegóły implementacji zostały naszkicowane bardziej szczegółowymi szczegółami.

Każdy element SiteMapNode ma właściwości, takie jak tytuł, adres URL, klucz i tak dalej

Rysunek 15. Każda z nich SiteMapNode ma właściwości takie jak Title, Url, Keyi tak dalej (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Mapa witryny jest dostępna za pośrednictwem SiteMap klasy w System.Web przestrzeni nazw. Ta właściwość klasy RootNode zwraca wystąpienie główne SiteMapNode mapy witryny. CurrentNode Zwraca SiteMapNode właściwość, której Url właściwość odpowiada adresowi URL aktualnie żądanej strony. Ta klasa jest używana wewnętrznie przez kontrolki nawigacji sieci Web ASP.NET 2.0.

SiteMap Gdy dostęp do właściwości klasy jest uzyskiwany, musi serializować strukturę mapy witryny z pewnego nośnika trwałego do pamięci. Jednak logika serializacji mapy witryny nie jest zakodowana w SiteMap klasie. Zamiast tego w czasie wykonywania SiteMap klasa określa, który dostawca mapy lokacji ma być używany do serializacji. Domyślnie XmlSiteMapProvider jest używana klasa , która odczytuje strukturę mapy witryny z poprawnie sformatowanego pliku XML. Jednak przy odrobinie pracy możemy utworzyć własnego niestandardowego dostawcę mapy witryny.

Wszyscy dostawcy map witryn muszą pochodzić z SiteMapProvider klasy, która zawiera podstawowe metody i właściwości wymagane dla dostawców mapy lokacji, ale pomija wiele szczegółów implementacji. Druga klasa, StaticSiteMapProvider, rozszerza klasę SiteMapProvider i zawiera bardziej niezawodną implementację wymaganych funkcji. Wewnętrznie program StaticSiteMapProvider przechowuje SiteMapNode wystąpienia mapy witryny w obiekcie Hashtable i udostępnia metody, takie jak AddNode(child, parent), RemoveNode(siteMapNode), oraz , które Clear() dodają i usuwają SiteMapNode s do wewnętrznego Hashtableelementu . XmlSiteMapProvider pochodzi z StaticSiteMapProvider.

Podczas tworzenia niestandardowego dostawcy mapy witryny, który rozszerza StaticSiteMapProviderprogram , istnieją dwie abstrakcyjne metody, które muszą zostać zastąpione: BuildSiteMap i GetRootNodeCore. BuildSiteMap, jak wskazuje jego nazwa, jest odpowiedzialny za ładowanie struktury mapy lokacji z magazynu trwałego i konstruowanie jej w pamięci. GetRootNodeCore Zwraca węzeł główny na mapie witryny.

Aby aplikacja internetowa mogła korzystać z dostawcy mapy witryny, musi zostać zarejestrowana w konfiguracji aplikacji. Domyślnie klasa jest rejestrowana XmlSiteMapProvider przy użyciu nazwy AspNetXmlSiteMapProvider. Aby zarejestrować dodatkowych dostawców map witryn, dodaj następujący znacznik do :Web.config

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

Wartość nazwy przypisuje do dostawcy nazwę czytelną dla człowieka, podczas gdy typ określa w pełni kwalifikowaną nazwę typu dostawcy mapy lokacji. Poznamy konkretne wartości nazw i typów w kroku 7 po utworzeniu niestandardowego dostawcy mapy witryny.

Klasa dostawcy mapy witryny jest tworzone po raz pierwszy z SiteMap klasy i pozostaje w pamięci przez cały okres istnienia aplikacji internetowej. Ponieważ istnieje tylko jedno wystąpienie dostawcy mapy witryny, które może być wywoływane z wielu, współbieżnych odwiedzających witrynę internetową, konieczne jest, aby metody dostawcy były bezpieczne wątkowo.

Ze względu na wydajność i skalowalność ważne jest, aby buforować strukturę mapy lokacji w pamięci i zwracać tę buforowana strukturę, a nie odtwarzać ją za każdym razem, gdy BuildSiteMap metoda jest wywoływana. BuildSiteMap Może być wywoływany kilka razy na żądanie strony dla użytkownika, w zależności od kontrolek nawigacji używanych na stronie i głębokości struktury mapy witryny. W każdym razie, jeśli nie buforujemy struktury mapy witryny za BuildSiteMap każdym razem, gdy jest wywoływana, musimy ponownie pobrać informacje o produkcie i kategorii z architektury (co spowodowałoby wysłanie zapytania do bazy danych). Jak omówiono w poprzednich samouczkach buforowania, buforowane dane mogą stać się nieaktualne. Aby temu przeciwdziałać, możemy użyć czasu lub wygaśnięcia opartego na zależnościach pamięci podręcznej SQL.

Uwaga

Dostawca mapy witryny może opcjonalnie zastąpić metodę Initialize. Initialize jest wywoływany po pierwszym utworzeniu wystąpienia dostawcy mapy lokacji i jest przekazywany wszelkie atrybuty niestandardowe przypisane do dostawcy w Web.config elemecie, <add> na przykład: <add name="name" type="type" customAttribute="value" />. Jest to przydatne, jeśli chcesz zezwolić deweloperowi strony na określanie różnych ustawień związanych z dostawcą mapy witryny bez konieczności modyfikowania kodu dostawcy. Jeśli na przykład odczytaliśmy dane kategorii i produktów bezpośrednio z bazy danych, w przeciwieństwie do architektury, prawdopodobnie chcemy zezwolić deweloperowi strony na określenie bazy danych parametry połączenia, Web.config zamiast używać wartości zakodowanej w kodzie dostawcy. Niestandardowy dostawca mapy witryny, który utworzymy w kroku 6, nie zastępuje tej Initialize metody. Przykład użycia Initialize metody można znaleźć w artykule Jeff Prosise s Storing Site Maps in SQL Server (Mapy witryn Storing w programie SQL Server ).

Krok 6. Tworzenie niestandardowego dostawcy mapy lokacji

Aby utworzyć niestandardowego dostawcę mapy witryny, który kompiluje mapę witryny z kategorii i produktów w bazie danych Northwind, musimy utworzyć klasę rozszerzającą klasę StaticSiteMapProvider. W kroku 1 poprosiłem Cię o dodanie folderu w App_Code folderze — dodaj nową klasę CustomProviders do tego folderu o nazwie NorthwindSiteMapProvider. Dodaj następujący kod do NorthwindSiteMapProvider klasy:

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?;
        }
    }
}

Zacznijmy od eksplorowania tej metody klasyBuildSiteMap, która zaczyna się od instrukcjilock . Instrukcja lock umożliwia wprowadzanie tylko jednego wątku, a tym samym serializowanie dostępu do kodu i zapobieganie przechodzeniu dwóch współbieżnych wątków na siebie nawzajem.

Zmienna root na poziomie SiteMapNode klasy służy do buforowania struktury mapy witryny. Po utworzeniu mapy lokacji po raz pierwszy lub po raz pierwszy po zmodyfikowaniu root danych bazowych zostanie null utworzona struktura mapy lokacji. Węzeł główny mapy lokacji jest przypisywany do root podczas procesu budowy, root tak aby przy następnym wywołaniu tej metody nie będzie .null W związku z tym tak długo, jak root nie null jest struktura mapy witryny zostanie zwrócona do obiektu wywołującego bez konieczności jego ponownego tworzenia.

Jeśli katalog główny to null, struktura mapy witryny jest tworzona na podstawie informacji o produkcie i kategorii. Mapa lokacji jest tworzona przez utworzenie SiteMapNode wystąpień, a następnie utworzenie hierarchii za pomocą wywołań StaticSiteMapProvider metody klasy s AddNode . AddNode wykonuje wewnętrzne księgowanie, przechowując wystąpienia assortowane SiteMapNode w obiekcie Hashtable. Zanim zaczniemy konstruować hierarchię, zaczynamy od wywołania Clear metody , która czyści elementy z wewnętrznej Hashtableklasy . ProductsBLL Następnie metoda s GetProducts klasy i wynikowe ProductsDataTable są przechowywane w zmiennych lokalnych.

Budowa mapy lokacji rozpoczyna się od utworzenia węzła głównego i przypisania go do rootelementu . Przeciążenie konstruktora używanego SiteMapNode tutaj i w tym BuildSiteMap miejscu jest przekazywane następujące informacje:

  • Odwołanie do dostawcy mapy witryny (this).
  • KeyS SiteMapNode . Ta wymagana wartość musi być unikatowa dla każdego SiteMapNodeelementu .
  • UrlS SiteMapNode . Url wartość jest opcjonalna, ale jeśli jest podana, każda SiteMapNode wartość s Url musi być unikatowa.
  • Parametr SiteMapNode s Title, który jest wymagany.

Wywołanie AddNode(root) metody dodaje SiteMapNode root element do mapy witryny jako katalog główny. Następnie każda ProductRow z nich jest ProductsDataTable wyliczana. Jeśli dla bieżącej kategorii produktu istnieje już element , SiteMapNode zostanie on przywołyny. W przeciwnym razie zostanie utworzony nowy SiteMapNode element kategorii i dodany jako element podrzędny SiteMapNode``root metody za pomocą wywołania AddNode(categoryNode, root) metody. Po znalezieniu lub utworzeniu odpowiedniego węzła kategorii SiteMapNode zostanie SiteMapNode utworzony dla bieżącego produktu i dodany jako element podrzędny kategorii SiteMapNode za pośrednictwem metody AddNode(productNode, categoryNode). Należy pamiętać, że wartość właściwości kategorii SiteMapNode to , gdy właściwość produktu Url SiteMapNode jest przypisana ~/SiteMapNode/ProductDetails.aspx?ProductID=productID.~/SiteMapProvider/ProductsByCategory.aspx?CategoryID=categoryID Url

Uwaga

Te produkty, które mają wartość bazy danych NULL dla nich CategoryID , są grupowane w kategorii SiteMapNode , której Title właściwość jest ustawiona na None i której Url właściwość jest ustawiona na pusty ciąg. Postanowiłem ustawić Url pusty ciąg, ponieważ ProductBLL metoda klasy s GetProductsByCategory(categoryID) obecnie nie ma możliwości zwrócenia tylko tych produktów z wartością NULL CategoryID . Chcę również zademonstrować, w jaki sposób kontrolki nawigacji renderują element SiteMapNode , który nie ma wartości dla jej Url właściwości. Zachęcam do rozszerzenia tego samouczka, aby właściwość None SiteMapNode Url wskazuje na ProductsByCategory.aspx, ale wyświetla tylko produkty z wartościami NULL CategoryID .

Po utworzeniu mapy witryny do pamięci podręcznej danych jest dodawany dowolny obiekt przy użyciu zależności Categories pamięci podręcznej SQL dla tabel i Products za pośrednictwem AggregateCacheDependency obiektu . W poprzednim samouczku zapoznaliśmy się z użyciem zależności pamięci podręcznej SQL, korzystając z zależności pamięci podręcznej SQL. Niestandardowy dostawca mapy lokacji używa jednak przeciążenia metody pamięci podręcznej Insert danych, którą jeszcze eksplorowaliśmy. To przeciążenie przyjmuje jako końcowy parametr wejściowy delegata, który jest wywoływany po usunięciu obiektu z pamięci podręcznej. W szczególności przekazujemy nowego CacheItemRemovedCallback delegata , który wskazuje metodę zdefiniowaną OnSiteMapChanged dalej w dół w NorthwindSiteMapProvider klasie.

Uwaga

Reprezentacja mapy witryny w pamięci jest buforowana za pomocą zmiennej rootna poziomie klasy . Ponieważ istnieje tylko jedno wystąpienie niestandardowej klasy dostawcy mapy witryny i ponieważ to wystąpienie jest współużytkowane przez wszystkie wątki w aplikacji internetowej, ta zmienna klasy służy jako pamięć podręczna. Metoda BuildSiteMap używa również pamięci podręcznej danych, ale tylko jako środek do odbierania powiadomień, gdy bazowe dane bazy danych w Categories tabelach lub Products zmieniają się. Należy pamiętać, że wartość umieszczona w pamięci podręcznej danych to tylko bieżąca data i godzina. Rzeczywiste dane mapy witryny nieumieszczane w pamięci podręcznej danych.

Metoda BuildSiteMap zostanie ukończona przez zwrócenie węzła głównego mapy witryny.

Pozostałe metody są dość proste. GetRootNodeCore jest odpowiedzialny za zwracanie węzła głównego. Ponieważ BuildSiteMap zwraca element główny, GetRootNodeCore po prostu zwraca BuildSiteMap wartość zwracaną przez element s. Metoda OnSiteMapChanged przywraca wartość root , null gdy element pamięci podręcznej zostanie usunięty. Po ponownym ustawieniu elementu głównego na nullelement zostanie wywołany element , przy następnym BuildSiteMap wywołaniu struktura mapy witryny zostanie ponownie skompilowana. CachedDate Na koniec właściwość zwraca wartość daty i godziny przechowywaną w pamięci podręcznej danych, jeśli taka wartość istnieje. Ta właściwość może być używana przez dewelopera strony w celu określenia, kiedy dane mapy witryny były ostatnio buforowane.

Krok 7. RejestrowanieNorthwindSiteMapProvider

Aby nasza aplikacja internetowa korzystała z dostawcy mapy witryny utworzonego NorthwindSiteMapProvider w kroku 6, musimy zarejestrować ją w <siteMap> sekcji .Web.config W szczególności dodaj następujący znacznik w elemecie w pliku <system.web> Web.config:

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

Ten znacznik wykonuje dwie czynności: najpierw wskazuje, że wbudowany AspNetXmlSiteMapProvider jest domyślnym dostawcą mapy witryny; drugi rejestruje niestandardowego dostawcę mapy witryny utworzonego w kroku 6 za pomocą przyjaznej dla człowieka nazwy Northwind.

Uwaga

W przypadku dostawców map witryn znajdujących się w folderze aplikacji App_Code wartość atrybutu type jest po prostu nazwą klasy. Alternatywnie niestandardowy dostawca mapy witryny mógł zostać utworzony w osobnym projekcie biblioteki klas z skompilowanym zestawem umieszczonym w katalogu aplikacji /Bin internetowej. W takim przypadku wartością atrybutu type będzie przestrzeń nazw.ClassName, AssemblyName .

Po zaktualizowaniu Web.configprogramu pośmiń chwilę, aby wyświetlić dowolną stronę z samouczków w przeglądarce. Pamiętaj, że interfejs nawigacyjny po lewej stronie nadal zawiera sekcje i samouczki zdefiniowane w pliku Web.sitemap. Jest to spowodowane tym, że pozostawiliśmy AspNetXmlSiteMapProvider go jako domyślnego dostawcę. Aby utworzyć element interfejsu użytkownika nawigacji korzystającego z NorthwindSiteMapProviderelementu , należy jawnie określić, że należy użyć dostawcy mapy witryny Northwind. Zobaczymy, jak to zrobić w kroku 8.

Krok 8. Wyświetlanie informacji o mapie witryny przy użyciu niestandardowego dostawcy mapy witryny

Za pomocą niestandardowego dostawcy mapy witryny utworzonego i zarejestrowanego w Web.configprogramie możemy dodać kontrolki nawigacji do Default.aspxstrony , ProductsByCategory.aspxi ProductDetails.aspx w folderze SiteMapProvider . Zacznij od otwarcia Default.aspx strony i przeciągnięcia SiteMapPath elementu z przybornika do projektanta. Kontrolka SiteMapPath znajduje się w sekcji Nawigacja w przyborniku.

Dodawanie ścieżki SiteMapPath do Default.aspx

Rysunek 16. Dodawanie ścieżki SiteMapPath do Default.aspx (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Kontrolka SiteMapPath wyświetla adres nadrzędny wskazujący bieżącą lokalizację strony w mapie witryny. Dodaliśmy ścieżkę SiteMapPath w górnej części strony wzorcowej z powrotem w samouczku Strony wzorcowe i Nawigacja witryny.

Pośmiń chwilę, aby wyświetlić tę stronę za pośrednictwem przeglądarki. Ścieżka SiteMapPath dodana na rysunku 16 używa domyślnego dostawcy mapy witryny, ściągając dane z programu Web.sitemap. W związku z tym linki do stron nadrzędnych zawierają stronę Home > Customizing the Site Map (Dostosowywanie mapy witryny), podobnie jak w przypadku stron nadrzędnych w prawym górnym rogu.

Do stron nadrzędnych jest używany domyślny dostawca mapy witryny

Rysunek 17. Link do stron nadrzędnych używa domyślnego dostawcy mapy witryny (kliknij, aby wyświetlić obraz pełnowymiarowy)

Aby obiekt SiteMapPath został dodany na rysunku 16, użyj niestandardowego dostawcy mapy witryny utworzonego w kroku 6, ustaw jej SiteMapProvider właściwość na Northwind, nazwę przypisaną NorthwindSiteMapProvider do elementu w Web.configpliku . Niestety projektant nadal używa domyślnego dostawcy mapy witryny, ale jeśli odwiedzasz stronę za pośrednictwem przeglądarki po wprowadzeniu tej zmiany właściwości, zobaczysz, że strona do stron nadrzędnych używa teraz niestandardowego dostawcy mapy witryny.

Zrzut ekranu przedstawiający sposób wyświetlania niestandardowego dostawcy mapy witryny.

Rysunek 18. Link do stron nadrzędnych używa teraz niestandardowego dostawcy NorthwindSiteMapProvider mapy witryny (kliknij, aby wyświetlić obraz pełnowymiarowy)

Kontrolka SiteMapPath wyświetla bardziej funkcjonalny interfejs użytkownika na ProductsByCategory.aspx stronach i ProductDetails.aspx . Dodaj ścieżkę SiteMapPath do tych stron, ustawiając SiteMapProvider właściwość w obu elementach na Northwind. Kliknij Default.aspx link Wyświetl produkty dla napojów, a następnie na link Wyświetl szczegóły dla Herbaty Chai. Jak pokazano na rysunku 19, strona do stron nadrzędnych zawiera bieżącą sekcję mapy witryny (Chai Tea) i jej przodków: Napoje i Wszystkie kategorie .

Zrzut ekranu przedstawiający sposób wyświetlania w witrynie bieżącej sekcji mapy witryny (Chai Tea) i jej przodków (Napoje i wszystkie kategorie).

Rysunek 19. Link do stron nadrzędnych używa teraz niestandardowego dostawcy NorthwindSiteMapProvider mapy witryny (kliknij, aby wyświetlić obraz pełnowymiarowy)

Inne elementy interfejsu użytkownika nawigacji mogą być używane oprócz kontrolki SiteMapPath, takich jak Menu i TreeView. ProductsByCategory.aspxStrony Default.aspx, i ProductDetails.aspx w pobranym pliku na potrzeby tego samouczka, na przykład wszystkie kontrolki menu dołączania (zobacz Rysunek 20). Zobacz ASP.NET zaawansowane funkcje nawigacji witryny w wersji 2.0 oraz sekcję Using Site Navigation Controls (Używanie kontrolek nawigacji lokacji) w przewodnikach Szybki start ASP.NET 2.0, aby uzyskać bardziej szczegółowe informacje na temat kontrolek nawigacji i systemu mapy lokacji w ASP.NET 2.0.

Kontrolka menu wyświetla listę poszczególnych kategorii i produktów

Rysunek 20. Kontrolka menu wyświetla listę poszczególnych kategorii i produktów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jak wspomniano wcześniej w tym samouczku, dostęp do struktury mapy witryny można uzyskać programowo za pośrednictwem SiteMap klasy . Poniższy kod zwraca katalog główny SiteMapNode domyślnego dostawcy:

SiteMapNode root = SiteMap.RootNode;

AspNetXmlSiteMapProvider Ponieważ jest to domyślny dostawca naszej aplikacji, powyższy kod zwróci węzeł główny zdefiniowany w pliku Web.sitemap. Aby odwołać się do dostawcy mapy witryny innej niż domyślna, użyj SiteMap właściwości klasy s Providers w następujący sposób:

SiteMapNode root = SiteMap.Providers["name"].RootNode;

Gdzie nazwa to nazwa niestandardowego dostawcy mapy witryny ( Northwind, dla naszej aplikacji internetowej).

Aby uzyskać dostęp do elementu członkowskiego specyficznego dla dostawcy mapy lokacji, użyj polecenia SiteMap.Providers["name"] , aby pobrać wystąpienie dostawcy, a następnie rzutować go do odpowiedniego typu. Aby na przykład wyświetlić NorthwindSiteMapProvider właściwość s CachedDate na stronie ASP.NET, użyj następującego kodu:

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!";
}

Uwaga

Pamiętaj, aby przetestować funkcję zależności pamięci podręcznej SQL. Po przejściu Default.aspxna strony , ProductsByCategory.aspxi ProductDetails.aspx przejdź do jednego z samouczków w sekcji Edytowanie, wstawianie i usuwanie oraz edytuj nazwę kategorii lub produktu. Następnie wróć do jednej ze stron w folderze SiteMapProvider . Zakładając, że dla mechanizmu sondowania minęło wystarczająco dużo czasu, aby zanotować zmianę w bazowej bazie danych, mapa witryny powinna zostać zaktualizowana w celu wyświetlenia nowej nazwy produktu lub kategorii.

Podsumowanie

funkcje mapy witryny ASP.NET 2.0 obejmują klasę SiteMap , szereg wbudowanych kontrolek nawigacji sieci Web oraz domyślnego dostawcę mapy witryny, który oczekuje, że informacje o mapie witryny utrwalone w pliku XML. Aby użyć informacji o mapie witryny z innego źródła, takiego jak z bazy danych, architektury aplikacji lub zdalnej usługi sieci Web, musimy utworzyć niestandardowego dostawcę mapy witryny. Obejmuje to utworzenie klasy, która pochodzi bezpośrednio lub pośrednio z SiteMapProvider klasy .

W tym samouczku pokazano, jak utworzyć niestandardowego dostawcę mapy witryny opartego na mapie witryny na podstawie informacji o produkcie i kategorii uszczepionych z architektury aplikacji. Nasz dostawca rozszerzył klasę StaticSiteMapProvider i wiązał się z utworzeniem BuildSiteMap metody, która pobierała dane, konstruowała hierarchię mapy lokacji i buforowała wynikową strukturę w zmiennej na poziomie klasy. Użyliśmy zależności pamięci podręcznej SQL z funkcją wywołania zwrotnego, aby unieważnić buforowaną strukturę podczas modyfikowania bazowych Categories danych lub Products danych.

Szczęśliwe programowanie!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

Informacje o autorze

Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w 24 godzinach. Można go uzyskać pod adresem mitchell@4GuysFromRolla.com. lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Recenzenci w tym samouczku to Dave Gardner, Zack Jones, Teresa Murphy i Bernadette Leigh. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.