How do database-driven web applications work

Create a Custom Database Driven Site Map (VB) provider

  • 28 minutes to read

by Scott Mitchell

Download code or download PDF

The default site map provider in ASP.NET 2.0 gets its data from a static XML file. Although the XML-based provider is suitable for many small and medium-sized websites, larger web applications require a more dynamic site map. In this tutorial, we'll create a custom site map provider that pulls its data from the business logic layer, which in turn pulls data from the database.


The ASP.NET 2.0S site map feature enables a page developer to define a website mapping for web applications in a persistent medium (e.g. in an XML file). After the site map data has been defined, it can be accessed programmatically through the class in the namespace or through a variety of navigationweb controls such as SiteMapPath, Menu, and TreeView controls. The site map system uses the provider model so that various implementations of site map serialization can be created and connected to a web application. The default site map provider that ships with ASP.NET 2.0 stores the site map structure in an XML file. In the tutorial on Master Pages and Website Navigation, we created a file named that contained this structure and whose XML code was updated with each new tutorial section.

The standard XML-based site map provider works well when the structure of the site map structure is fairly static; b. for these tutorials. However, in many scenarios a more dynamic site map is required. Take a look at the site map shown in Figure 1, with each category and product shown as sections in the structure of the site. When this site map is displayed, you can list all categories by going to the webpage corresponding to the root node, while visiting a specific category on the webpage will list the products category and display a specific product e-page .

illustration 1: the categories and products included in the structure of the site map structure (click to view full size image)

This category and product-based structure can be hard-coded into the file, but the file must be updated every time a category or product is added, removed, or renamed. As a result, the maintenance of the site map is greatly simplified if the structure has been obtained from the database or, ideally, from the business logic layer of the application architecture. This way, as you add, rename, or delete products and categories, the Site Map is automatically updated to reflect these changes.

Since the ASP.NET 2.0s site map serialization was created through the provider model, we can create our own custom site map provider that draws its data from an alternative data store, such as a web site. b. the database or the architecture. In this tutorial, we will create a custom provider that will pull its data from the BLL. Get started


The custom site map provider created in this tutorial is closely tied to the architecture and data model of the application. Jeff Prosise's stores site maps in SQL Server, and the SQL Site Map Provider you've been waiting for articles are exploring a generalized approach to storing site map data in SQL Server.

Step 1: Create the custom website overview provider websites

Before we start creating a custom site map provider, you can first add the ASP.NET pages required for this tutorial. First, add a new folder with the name. Then add the following ASP.NET pages to this folder and make sure to map each page to the master page:

    Also add a subfolder to the folder.

    Figure 2: Adding the ASP.NET pages for the site map provider related tutorials

    Since there is only one tutorial for this section, we do not need to list the tutorials for that section. Instead, the categories are displayed in a GridView control. This is covered in step 2.

    Then update to include a reference to the page. In particular, add the following markup after caching:

    After updating, take a moment to view the Tutorials website through a browser. The menu on the left now contains an item for the only site map provider tutorial.

    Figure 3: the site map now contains an entry for the site map provider tutorial.

    This tutorial mainly focuses on creating a custom site map provider and configuring a web application to use that provider. Specifically, we'll create a provider that will return a site map that has a root node along with a node for each category and product, as shown in Figure 1. In general, each node in the site map can specify a URL. For our site map, it will be the URL of the root node, which will list all of the categories in the database. Each category node in the site map has a URL that points to all of the products in the specified CategoryIDbe listed. Finally, each Product Site Map node points out where the details of that particular product are displayed.

    First the pages, and have to be created. These pages are completed in steps 2, 3 and 4, respectively. Since this tutorial is about Site Map Providers and the last few tutorials explained how to create these types of multi-page master / detail reports, steps 2 through 4 are described. If you need a master / detail report updater that spans multiple pages, see the tutorial on how to filter master / detail over two pages.

    Step 2: Viewing a List of Categories

    Open the page in the folder and drag a GridView from the Toolbox onto the designer and set its to. Bind the GridView s smart tag to a new named ObjectDataSource and configure it to get your data using the Class s method. Since only the categories are displayed in this GridView and no data change functions are provided, set the drop-down lists on the Update, Insert and Delete tabs to (none).

    Figure 4: Configuring ObjectDataSource to Return Categories Using the Method (Click to view full size image)

    Figure 5: Set the drop-down lists on the Update, Insert, and Delete tabs to (none) (click to view full-size image)

    After completing the Data Source Configuration Wizard, Visual Studio will add a BoundField element for,,, and. Edit the GridView to include only the and boundfields and update the BoundField s property to Category.

    Next, add a HyperLinkField and position it so that it is the leftmost field. Set the property to and the property to. Set the property to Show Products.

    Figure 6: Adding a HyperLinkField to the GridView

    After you've created the ObjectDataSource and customized the GridView's fields, the two controls declarative markup will look like this:

    Figure 7 shows when viewed in a browser. Clicking the View Products link will take you to the one we will create in Step 3.

    Figure 7: each category is listed along with the link "view products" (click to view full size image)

    Step 3: List the products of the selected category

    Open the "" page and add a GridView. Bind the GridView object from the smart tag to a new ObjectDataSource with the name. Configure the ObjectDataSource to use the Class s method and set the drop-down list to (None) on the Update, INSERT, and DELETE tabs.

    Figure 8: Using the Class s Method (click to view full size image)

    In the final step of the Data Source Configuration Wizard, you will be prompted for a parameter source for CategoryIDto enter. Since this information is passed through the QueryString field, select QueryString from the drop-down list and enter CategoryID in the QueryStringField text box, as shown in Figure 9. Click Finish to complete the wizard.

    Figure 9: Using the QueryString field for the CategoryID -Parameters (click to view full size image)

    After you have completed the wizard, Visual Studio adds the appropriate boundfields and a CheckBoxField to the GridView for the Product Data fields. Remove all but the, and boundfields. Adjust these three boundfields properties to read Product, Price, and Supplier. Format the BoundField as currency.

    Next, add a HyperLinkField and move it to the left position. Set the property to Show Details, the property to and its property to.

    Figure 10: Adding a HyperLinkField for view details that is on

    After making these adjustments, the declarative markup of the GridView and ObjectDataSource tables should look similar to the following:

    Go back to viewing from a browser and click the View Products link for Beverage. This allows you to view the names, prices, and suppliers of the products in the Northwind database that belong to the Beverages category (see Figure 11). You can further enhance this page to add a link to return users to the category listing page () and the DetailsView or FormView control, which shows the name and description of the selected category.

    Figure 11: the names, prices and suppliers of the drinks are displayed (click to view full size image)

    Step 4: Viewing the details of a product

    The last page,, shows the details of the selected products. Open and drag a DetailsView from the Toolbox onto the designer. Set the DetailsView s property to and clear its and property values. In the smart tag, bind the DetailsView to a new ObjectDataSource named and configure the ObjectDataSource to get your data from the Class s method. As with the previous web pages created in steps 2 and 3, set the drop-down lists on the Update, Insert, and Delete tabs to (none).

    Figure 12: Configuring ObjectDataSource to Use the Method (Click to view full size image)

    The final step of the Data Source Configuration Wizard asks you to select the source of the ProductID- Enter parameters. Because this data traverses the QueryString field, set the drop-down list to QueryString and the text box QueryStringField to ProductID. Finally, click the Finish button to complete the wizard.

    Figure 13: Configuring the ProductID- Parameter to get its value from QueryString field (Click to view full size image)

    After completing the wizard for configuring data sources, Visual Studio creates the corresponding boundfields and a CheckBoxField in the DetailsView for the Product Data fields. Remove the, and boundfields and configure the remaining fields as shown. After some aesthetic configuration, my DetailsView and ObjectDataSource s declarative markup looked like this:

    To test this page, return to and click View Products for the Beverages category. In the list of beverage products, click the View details link for Chai Tea. This will take you to where the details of Chai Tea are displayed (see Figure 14).

    Figure 14: the manufacturer, category, price and other information of Chai Tea s are displayed (click to view full size image)

    Step 5: Understand the inner workings of a site map provider

    The site map is displayed in the memory of the web server as a list of instances that form a hierarchy. There must be exactly one root, all non-root nodes must have a parent node, and all nodes may have any number of child nodes. Each object represents a section in the structure of the website. A corresponding web page is often displayed in these sections. As a result, the class has properties such as, and, that provide information for the section represented by the. There is also a property that uniquely identifies each in the hierarchy, as well as properties that define that hierarchy,,, etc.

    Figure 15 shows the general site map structure from Figure 1, but with the implementation details presented in more detail.

    Figure 15: each has properties like,, etc. (click to view full size image)

    The site map can be accessed via the class in the namespace. This Class s property returns the root instance of the site map s. returns the one whose property matches the URL of the currently requested page. This class is used internally by ASP.NET 2.0S navigation web controls.

    When the properties of the class are accessed, the site map structure must be serialized into memory from persistent media. However, the site map serialization logic is not hard-coded in the class. Instead, the class determines which site map at runtime providers should be used for serialization. By default, the class is used, which reads the structure of the site map structure from a properly formatted XML file. However, with a little work we can create our own custom site map provider.

    All site map providers must be derived from the class, which contains the basic methods and properties required of site map providers, but omits many of the implementation details. A second class,, extends the class and contains a more robust implementation of the functionality required. Internally, the saves the instances of the site mapping and provides methods such as, and that add or remove s from the internal. is derived from.

    When creating a custom site map provider that extends, there are two abstract methods that must be overridden: and. , as the name suggests, is responsible for loading the site map structure from permanent storage and creating it in memory. returns the root node in the site map.

    Before a web application can use a site map provider, it must be registered in the application's configuration. By default, the class is registered with the name. To register additional site map providers, add the following markup:

    The Surname -Value assigns a human-readable name to the provider while Type Specifies the fully qualified type name of the site map provider. We examine specific values ​​for the Names and the Type values in step 7 after we've created our custom site map provider.

    The Site Map Provider class is instantiated by the class when it is first accessed and remains in memory for the life of the web application. Since there is only one instance of the site overview provider that can be accessed by several parallel visitors to the website, it is imperative that the methods of the provider Thread safeare.

    For performance and scalability, it is important that we cache the in-memory site map structure and return that cached structure, rather than re-creating it every time the method is called. can be accessed multiple times per page request per user, depending on the navigation controls used on the page and the depth of the site map structure.If we didn't cache the site map structure in any case, we would have to fetch the product and category information from the architecture again every time it is called (which would result in a query of the database). As explained in the previous caching tutorials, cached data can become stale. To combat this we can use either time or SQL cache dependency based flows.


    A site map provider can optionally override the method. invoked when the site map provider is first instantiated and any custom attributes assigned to the provider are assigned in the How element. It is useful when you want to allow a page developer to specify various settings for the site map provider without having to change the provider e-code. If we e.g. b. Reading the category and product data directly from the database rather than the architecture, we probably want the site developer to specify the database connection string via rather than using a hard-coded value in the vendor's e-code. The custom site map provider we create in step 6 does not override this method. For an example of using the method, see Jeff Prosise s Saving Site Maps in SQL Server article.

    Step 6: Create the custom site map provider

    To create a custom site map provider that creates the site map from the categories and products in the Northwind database, a class must be created that extends. In Step 1, you asked to add a folder under the "" folder. Add a new class to this folder. Add the following code to the class:

    Start by examining this Class s method, which begins with a statement. The instruction can only enter one thread at a time. this serializes access to the code and prevents two concurrent threads from kicking each other.

    The class level variable is used to cache the site map structure. When the site map is created for the first time, or the first time after the underlying data has been changed, and the structure of the site structure is created. The root node of the site map is assigned during the build process, so it won't be the next time this method is called. As a result, the structure of the site map is not returned to the caller without having to recreate it.

    If root, the site map structure is created from the product and category information. The site map is created by creating the instances and then building the hierarchy by calling the method of the class. carries out the internal bookkeeping, whereby the various instances are stored in one. Before we start creating the hierarchy, let's first call the method, which will delete the elements from the internal. Next, the class method and the resulting are stored in local variables.

    The creation of the site map begins with creating the root node and assigning it to it. The overload of the s constructor used here and in this one is passed the following information:

    • A reference to the site overview provider ().
    • The s. This required value must be unique to each.
    • The s. is optional, but when provided, each s value must be unique.
    • The s that is needed.

    The method call adds the as a root to the site map. The next step is to list each in the. If one already exists for the current Products category, it will be referenced. Otherwise a new one is created for the category and added as a child element of the using the method call. After the appropriate category node has been found or created, one is created for the current product and added as a child of the category via. Notice that the Category s property is Value while the Product is assigned s property.


    Products that have a database value for yours are grouped under a category whose property is set to None and whose property is set to an empty string. I chose to set it to an empty string because the Class s method does not currently have the ability to return only those products with a value. I also wanted to demonstrate how the navigation controls render a rendering that does not contain a value for the property. I recommend expanding this tutorial so that the property does not refer to any s, but only shows the products with values.

    After the site overview has been created, any object with an SQL cache dependency and tables is added to the data cache via an object. We saw the use of SQL cache dependencies in the previous tutorial below Use of SQL cache dependenciesexamined. However, the custom site map provider uses an overload of the Data Cache s method that we can still investigate. This overload accepts as the final input parameter a delegate that is invoked when the object is removed from the cache. In particular, we are passing a new delegate that references the method defined below in the class.


    The internal memory representation of the site map is cached by the variable at the class level. Since there is only one instance of the custom site map provider class and this instance is shared by all threads in the web application, this class variable serves as a cache. The method also uses the data cache, but only as a means of receiving notifications when the underlying database data in the or tables changes. Note that the value placed in the data cache is only the current date and time. The actual site map data will be Not inserted into the data cache.

    The method is completed by returning the root node of the site map.

    The rest of the methods are fairly straightforward. is responsible for returning the root node. Since the trunk returns, it simply returns s-return value. The method reverts to when the cache item is removed. If "root" is reset to "", the site map structure will be rebuilt the next time you use. Finally, the property returns the cached date and time value, if such a value is present. This property can be used by a page developer to determine when the site map data was last cached.

    Step 7: Register the

    In order for the web application to use the site map provider created in step 6, we need to register it in the section of. In particular, add the following markup within the element:

    This markup does two things. First, it indicates that the built-in is the default site map provider. Second, you registered the custom site map provider that was created in step 6 with the humane name "Northwind".


    For site map providers located in the "Applications" folder, the value of the attribute is simply the class name. Alternatively, the custom site map provider may have been created in a separate class library project by placing the compiled assembly in the web application directory. In this case the value of the attribute would be " Namespace". ClassName, AssemblyName .

    After refreshing, take a moment to view any page from the tutorials in a browser. Notice that the navigation interface on the left still shows the sections and tutorials that are defined in. This is because we left as the default provider. To create a navigation UI element that uses the, we must explicitly indicate that the Northwind Site Map provider should be used. This is explained in step 8.

    Step 8: View Site Map Information Using the Custom Site Map Provider

    After you've created and registered your custom site map provider in, you can add the navigation controls to the, and pages in the folder. First, open the page and drag one from the toolbox onto the designer. The SiteMapPath control is located in the navigation area of ​​the toolbox.

    Figure 16: Adding a SiteMapPath to (click to view full size image)

    The SiteMapPath control displays a breadcrumb value that indicates the position of the current page within the site map. We got in the tutorial too Master pages and website navigation Added a SiteMapPath at the top of the master page.

    Take a moment to view this page through a browser. The SiteMapPath added in Figure 16 uses the default site map provider and extracts its data. The breadcrumb code therefore shows Start> Site Map Customization, just like the breadcrumb in the top right corner.

    Figure 17: Breadcrumb uses the default site map provider (click to view full size image)

    To add SiteMapPath in Figure 16, use the custom site map provider you created in step 6, set the property to Northwind, the name you assigned to it. Unfortunately the designer is still using the default site map provider, but if you visit the page from a browser after changing this property you will see that the breadcrumb is now using the custom site map provider.

    Figure 18: Breadcrumb is now using the custom site map provider (click to view full size image)

    The SiteMapPath control displays a more functional user interface on the and pages. Add a SiteMapPath property to these pages by setting the property in Northwind. In, click the View Products link, and then click the View Details link for Chai Tea. As shown in Figure 19, the breadcrumb contains the current site overview section (Chai Tea) and its predecessors: beverages and all categories.

    Figure 19: Breadcrumb is now using the custom site map provider (click to view full size image)

    In addition to SiteMapPath, other elements of the navigation user interface can also be used, such as: b. the menu and TreeView controls. The pages, and in the download for this tutorial, e.g. b. all menu controls included (see Figure 20). For a more in-depth look at the navigation controls and site map system in ASP.NET 2.0, see Finding ASP.NET 2.0s Web Site Navigation Features and the Using Site Navigation Controls section of ASP.NET 2.0 Quick starts.

    Figure 20: the menu control lists the individual categories and products (click to view full size image)

    As mentioned earlier in this tutorial, the site map structure can be accessed programmatically through the class. The following code returns the root of the default provider:

    Since that is the default provider for the application, the code above would return the root node defined in. If you want to reference a different site map provider than the default referral, use the class property as follows:

    It is Surname the name of the custom site map provider (Northwind for the web application).

    To access a provider-specific member for a site map, use to get the provider instance, and then cast it to the appropriate type. Use e.g. b. the following code to display the s property on an ASP.NET page:


    Make sure to test the SQL cache dependency feature. After visiting pages,, and, navigate to one of the tutorials in the edit, insert and delete section, and edit the name of a category or product. Then return to one of the pages in the folder. Assuming that enough time has passed for the retrieval mechanism to note the change to the underlying database, the site mapping should be updated to reflect the new product or category name.


    ASP.NET 2.0s site map features include a class, a number of built-in web controls for navigation, and a default site map provider that expects the site map information to be stored in an XML file. To use site map information from another source (e.g. from a database, application architecture, or remote web service) we need to create a custom site map provider. This involves creating a class that derives directly or indirectly from the class.

    This tutorial explained how to create a custom site map provider that built the site map based on the product and category information based on the application architecture. The provider extended the class and created a method to get the data, build the site map hierarchy, and cache the resulting structure in a variable at the class level. We used a SQL cache dependency with a callback function to invalidate the cached structure when the underlying or data is changed.

    Happy programming!

    Other useful information

    For more information on the topics covered in this tutorial, see the following resources:

    To the author

    Scott Mitchell, author of the seven ASP / ASP. net books and founder of, has worked with Microsoft web technologies since 1998. Scott works as an independent consultant, instructor and writer. His last book is Sams Teach Yourself ASP.NET 2.0 in 24 hours. He can be reached at [email protected] or see his blog at http://ScottOnWriting.NET.

    Thank you very much

    This series of tutorials has been reviewed by many helpful reviewers. The lead reviewers for this tutorial were Dave Gardner, Zack Jones, Teresa Murphy, and Bernadette Leigh. Would you like to review my upcoming MSDN articles? If so, you can drop a line in [email protected]