January 2018 : Instructor-led Online Course in ASP.NET Core 2.0. Conducted by Bipin Joshi. Read more...
Registration for January 2018 batch of ASP.NET Core 2.0 instructor-led online course has already started. Conducted by Bipin Joshi. Register today ! Click here for more details.

Using Site Maps to provide web site navigation

Introduction

If you anytime traveled to unknown areas you know the importance of maps. They help you to travel easily making your journey pleasurable. The same holds true for web sites. The visitors coming to your web sites should be presented with simple yet flexible navigation structure so that they can travel to various parts of your web site easily. ASP.NET provides a feature called SiteMap that help you achieve this goal. In this article we will explore what site maps are and how to develop web site navigation structures making use of them.

The SiteMap

A site map is an XML file that details the overall navigational layout of your web site. You can then consume this site map file as per your requirement. The site map file must have extension .sitemap.

Let's understand the site map files with an example. Have a look at Figure 1

Figure 1: Web site structure

Here, we have directory structure of a sample web site. The home page (Default.aspx) and Contact Us page (contact.aspx) are residing in the root folder of the web site. There are two sub folders called Products and Services. Each have two web forms - Product1.aspx, Product2.aspx and Service1.aspx and Service2.aspx - respectively.

Now let's represent this web site structure using a site map.

Create a new web site using Visual Studio. Right click on the web site and choose "Add New Item...". Select Site Map from the "Add New Item..." dialog (see Figure 2) and give name as Web.sitemap.

Figure 2: Adding a new site map

Now key in the following XML markup in the web.sitemap file.

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/
AspNet/SiteMap-File-1.0" >
<siteMapNode url="default.aspx" title="Home" 
description="My Web Site">
  <siteMapNode url="~/products/default.aspx" 
title="Products">
    <siteMapNode url="~/products/product1.aspx" 
title="First Product" />
    <siteMapNode url="~/products/product2.aspx" 
title="Second Product" />
  </siteMapNode>
  <siteMapNode url="~/services/default.aspx" 
title="Services">
    <siteMapNode url="~/services/service1.aspx" 
title="First Service" />
    <siteMapNode url="~/services/service2.aspx" 
title="Second Service" />
  </siteMapNode>
<siteMapNode url="contact.aspx" title="Contact Us" />
</siteMapNode>
</siteMap>

The root of site map file is siteMap. It further contains a node called siteMapNode. Inside it contains several siteMapNodes depending on your web site structure.

The siteMapNode tag has four important attributes. They are listed in Table 1:

Attribute Description
title Indicates the title of the page. This attribute is often used by navigation controls to display title for the URL.
url Indicates the URL of the page that this node represents
description Specifies description of this page. You can use this description to show tooltips
roles While using security trimming (discussed later) this attribute specifies the roles that are allowed to access this page

Table 1: Important attributes of <siteMapNode> tag

This makes your site map. You can now think of using it for navigation purpose.

Ways to consume SiteMap

Site map files are often used to render some kind of navigation structure. There are three common ways in which you can consume the site map file we just created:

  • Use SiteMapPath control
  • Use SiteMap Data Source control
  • Use SiteMap class

The SiteMapPath control allows you to render what is often called as "breadcrumbs". Figure 3 shows what breadcrumbs are:

Figure 3: Breadcrumb navigation

The SiteMapPath controls displays various levels of navigation. You can click on parent or root levels to navigate back or at the top level. You can of course customize the navigation levels.

ASP.NET 2.0 comes with nice set of navigation controls that include TreeView and menu. You can bind the site map file with these controls with the help of SiteMap Data Source control.

At times the inbuilt navigation controls may not meet your requirement. In such cases you can access the site map file programmatically and read various siteMapNodes. You can then render a custom navigation structure using title and url attributes of siteMapNode.

Using SiteMapPath control

Before we delve into mode details let's first create the required directory structure and web forms. Begin by adding two folders to the web site called Products and Services. Then add a new Master Page to the web site called MasterPage.master. Add the web forms as shown in Table 2. Make sure to set master page for all of them while adding.

Web Form name Folder
Default.aspx Web site root
Contact.aspx Web site root
Default.aspx Products
Product1.aspx Products
Product2.aspx Products
Default.aspx Services
Service1.aspx Services
Service2.aspx Services

Table 2: List of web forms

Now, open the Master Page that we added previously. Drag and drop a Label control and a SiteMapPath control on it (SiteMapPath control can be found in the Navigation node of the VS.NET Toolbox). Set the Text property of the Label to "Welcome!".

The following listing shows the complete markup of MasterPage.master.

<%@ Master Language="C#" AutoEventWireup="true" 
CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Font-Size="XX-Large" 
ForeColor="Blue" Text="Welcome!"></asp:Label><br />
<asp:SiteMapPath ID="SiteMapPath1" runat="server" 
Font-Names="Verdana" Font-Size="0.8em"
PathSeparator=" : ">
<PathSeparatorStyle Font-Bold="True" ForeColor="#5D7B9D" />
<CurrentNodeStyle ForeColor="#333333" />
<NodeStyle Font-Bold="True" ForeColor="#7C6F57" />
<RootNodeStyle Font-Bold="True" ForeColor="#5D7B9D" />
</asp:SiteMapPath>
<br />
<br />
<asp:contentplaceholder id="ContentPlaceHolder1" 
runat="server">
</asp:contentplaceholder>
</div>
</form>
</body>
</html>

Now open Default.aspx from the root folder. The Default.aspx should look like Figure 4.

Figure 4: Sample run of Default.aspx

In order to design this page, add a table with four rows and one column. Dran and drop a Label control in the topmost row and set its Text property to "Welcome to our web site!". Then drag and drop three HyperLink controls in the remaining rows and set their Text and NavigateUrl properties as shown below:

HyperLink ID Text property NavigateUrl property
HyperLink1 Products ~/products/default.aspx
HyperLink2 Services ~/Services/default.aspx
HyperLink3 Contact Us ~/contact.aspx

Table 3: Setting properties of HyperLinks

The following listing shows the complete markup of Defaule.aspx

<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" 
AutoEventWireup="true" CodeFile="Default.aspx.cs"
 Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" 
ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<center>
<table>
<tr>
<td width="60%">
<asp:Label ID="Label1" runat="server" Font-Size="X-Large" 
Text="Welcome to our web site!"></asp:Label></td>
</tr>
<tr>
<td width="60%">
<asp:HyperLink ID="HyperLink1" runat="server" 
Font-Size="X-Large" NavigateUrl="~/Products/Default.aspx">
Products</asp:HyperLink></td>
</tr>
<tr>
<td width="60%">
<asp:HyperLink ID="HyperLink2" runat="server" 
Font-Size="X-Large" NavigateUrl="~/Services/Default.aspx">
Services</asp:HyperLink></td>
</tr>
<tr>
<td width="60%">
<asp:HyperLink ID="HyperLink3" runat="server" 
Font-Size="X-Large" NavigateUrl="~/Contact.aspx">
Contact Us</asp:HyperLink></td>
</tr>
</table>
</center>
</asp:Content>

Now open Default.aspx from Products folder and design it as shown in Figure 5.

Figure 5: Default page of Products folder

The following table lists the HyperLinks used in the web form.

HyperLink ID Text property NavigateUrl property
HyperLink1 First Product ~/products/product1.aspx
HyperLink2 Second Product ~/products/product2.aspx

Table 4: HyperLinks of default page from Products folder

On the similar lines design Default.aspx from Services folder as shown in Figure 6:

Figure 6: Default page of Services folder

The following table lists the HyperLinks used in the web form.

HyperLink ID Text property NavigateUrl property
HyperLink1 First Service ~/Services/service1.aspx
HyperLink2 Second Service ~/Services/service2.aspx

Table 5: HyperLinks of default page from Products folder

Finally, add one label to all the remaining web forms and set its Text property as shown in Table 6:

Web Form name Text property of Label
~/Contact.aspx Contact Us
~/Products/Product1.aspx First Product Details
~/Products/Product2.aspx Second Product Details
~/Services/Service1.aspx First Service Details
~/Services/Service2.aspx Second Service Details

Table 6: Setting Text property of Labels from remaining web forms

Now, run the Default.aspx from the root folder and navigate to Product1.aspx page. Figure 7 shows the sample run of the web form.

Figure 7: Sample run of Product1.aspx

Note how title and url attributes from the web.sitemap file is used to render the "breadcrumbs". Also, note how the parent levels are displayed along with the current page title. Try navigating to various pages and observe the SiteMapPath control.

Using SiteMap Data Source control

The use of site maps is not limited just to SiteMapPath control. You can also attach the site map to navigational controls such as TreeView. In this example we will use the same site map file to bind with a TreeView.

Add a new web form called SiteMapDataSourceDemo.aspx to the web site. Drag and drop a SiteMap Data Source control (SiteMapDataSource1) and a TreeView (TreeView1). Set the DataSourceID property of the TreeView to SiteMapDataSource1. Also, set ShowLines property of TreeView control to true. Below is the complete markup of SiteMapDataSourceDemo.aspx.

<%@ Page Language="C#" AutoEventWireup="true" 
CodeFile="SiteMapDataSourceDemo.aspx.cs"
 Inherits="SiteMapDataSourceDemo" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:TreeView ID="TreeView1" runat="server"
 DataSourceID="SiteMapDataSource1" ShowLines="True">
</asp:TreeView>
<asp:SiteMapDataSource ID="SiteMapDataSource1" 
runat="server" />
</form>
</body>
</html>

Now run the web form and see how the same navigation structure is automatically rendered in the TreeView (Figure 8).

Figure 8: Binding site map file to a TreeView

Using SiteMap class

Displaying site map data in SiteMapPath or TreeView control works great. However, at times you may need to device a custom rendering logic. For example, you may want to develop a custom navigation control that displays only the parent levels; that too in vertical direction. In such cases you need to access the site map file programmatically. The SiteMap class allows you to do exactly that.

The SiteMap path has two important properties - RootNode and CurrentNode. Both of these properties are of type SiteMapNode and give you the reference of root node and current node of the site map respectively. The Table 7 lists some of the important properties of SiteMapNode class.

Property Description
ChildNodes Represents the collection of all the child nodes of the current node
HasChildNodes Indicates whether the site map node has child nodes (true/false)
Title Returns the value of title attribute as specified in the site map file
Url Returns the value of url attribute as specified in the site map file
Description Returns the value of description attribute as specified in the site map file
ParentNode Gives reference of the parent site map node of current node

In the following example we will use SiteMap path to access the individual nodes of site map file. We then programmatically add them to a TreeView control.

Add a new web form called SiteMapCustom.aspx. Drag and drop a TreeView control on it. Add the following code to the Page_Load event of the web form.

protected void Page_Load(object sender, EventArgs e)
{
int count = SiteMap.RootNode.ChildNodes.Count;
for (int i = 0; i < count; i++)
{
SiteMapNode smNode=SiteMap.RootNode.ChildNodes[i];
TreeNode tvNode = new TreeNode
(smNode.Title, "", "",smNode.Url, "");
TreeView1.Nodes.Add(tvNode);
if (smNode.HasChildNodes)
{
int childCount=smNode.ChildNodes.Count;
for (int j = 0; j < childCount; j++)
{
SiteMapNode smChildNode = smNode.ChildNodes[j];
TreeNode tvChildNode = new TreeNode
(smChildNode.Title, "", "", smChildNode.Url, "");
tvNode.ChildNodes.Add(tvChildNode);
}
}
}
}

Here, we first get the total number of child nodes of the root node. Then we loop through the ChildNodes collection of the root node. With each iteration we create a new instance of TreeNode class and specify its title and url in its constructor. We then add this TreeNode to the Nodes collection of the TreeView. We check if the current SiteMapNode has any child nodes. If it does have child nodes we iterate through them repeating the TreeNode creation process. Note that this time we add the new TreeNodes to the ChildNodes collection of the current TeeNode object.

Note that since we know that there are only two levels of nesting we used two for loops. To make your logic more generic you may use recursion to populate the TreeView.

Run the web form and you should again see something as shown in Figure 8.

Using security trimming

Web site often implement role based security schemes. For example, you may have different roles in your application such as Administrators, ProductTesters and ServiceTesters. In such cases you frequently need to control the site navigation links shown to the users. For example you may want that if the currently logged in user belongs to ProductTesters role then on the links related to products should be displayed otherwise they should be hidden from him. One way to deal this way is via manual coding but it will involve programmatically taking care of all the authorization logic. Fortunately, the site map file and SiteMap Data Source control together provide a feature called security trimming that helps you achieve just that.

In order to test security trimming you need to enable membership and roles features to your web site. Open the web.config file and add the following markup in it:

<authentication mode="Forms" />
<authorization>
<deny users="?"></deny>
</authorization>

Here we set authentication mode to Forms. We also set authorization rule such that anonymous users are denied access to the web site. We also need to enable role management feature by adding the following tag to the web.config file:

<roleManager enabled="true" />

Next, select WebSite > ASP.NET Configuration from the VS.NET menu bar to open Web Site Administration Tool. Using the tool add two roles - ProductTesters and ServiceTesters (Figure 9). We want that when user belonging to ProductTesters role signs in only the product related links should be displayed in the navigation TreeView. Similarly when user belonging to ServiceTesters role signs in only the service related links should be displayed in the TreeView

Figure 9: Adding roles using Web Site Administration Tool

Create two users using the Web Site Administration Tool called user1 and user2. Add user1 to ProductTesters role and user2 to ServiceTesters role (Figure 10).

Figure 10: Creating users using Web Site Administration Tool

NOTE: By default user and role information is stored in ASPNETDB database from App_Data folder of your web site. This database is automatically created by ASP.NET if it doesn't exists.

Now add a new site map file named SecurityTrimming.sitemap to the web site and key in the following markup in it:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/
AspNet/SiteMap-File-1.0" >
<siteMapNode url="default.aspx" title="Home" 
description="My Web Site">
<siteMapNode title="Products" roles="ProductTesters">
<siteMapNode url="~/products/product1.aspx" 
title="First Product" />
<siteMapNode url="~/products/product2.aspx" 
title="Second Product" />
</siteMapNode>
<siteMapNode title="Services" 
roles="ServiceTesters">
<siteMapNode url="~/services/service1.aspx" 
title="First Service" />
<siteMapNode url="~/services/service2.aspx" 
title="Second Service" />
</siteMapNode>
<siteMapNode url="contact.aspx" title="Contact Us" />
</siteMapNode>
</siteMap>

Most of the markup is the same as we wrote in web.sitemap file earlier. However, there is one important attribute - roles - added to Products and Services siteMapNodes. The roles attribute specifies the role for which this node and its child nodes are accessible. Since Products related links are to be displayed only to the users belonging to ProductTesters we set roles attribute of Products siteMapNode to ProductTesters. On the same lines we set roles attribute of Services siteMapNode to Servicetesters. The siteMapNodes that do not have roles attribute specified are accessible to all the users. Also, note that Products and Services nodes no longer have url attribute specified.

Now we need to configure the site map provider and enable security trimming so that SiteMap Data Source control can do the needful for us. Add the following markup in web.config file:

<siteMap defaultProvider="myprovider"
 enabled="true">
<providers>
<add name="myprovider"
type="System.Web.XmlSiteMapProvider "
siteMapFile="SecurityTrimming.sitemap"
securityTrimmingEnabled="true" />
</providers>

Here, we add <siteMap> section and specify a provider pointing to SecurityTrimming.sitemap file. Note that securityTrimmingEnabled attribute is set to true to enable security trimming. Once we configure the <siteMap> section the SiteMap Data Source control will automatically pickup setting from this section.

Add a new web form to the web site called Login.aspx. Drag and drop a Login control on it and set its DestinationPageUrl property to "~/SiteMapDataSourceDemo.aspx". We developed SiteMapDataSourceDemo.aspx previously (refer section titled "Using SiteMap Data Source control").

Run the Login.aspx (Figure 11) and enter credentials for user1.

Figure 11: Login page

Once you login successfully you should see the TreeView as shown in Figure 12. Since user1 belongs to ProductTesters role the service related links are hidden.

Figure 12 : Security Trimming in action

Summary

Site map is an XML file that details the structure of your web site. You can consume site map file to generate navigation structures. There are three common ways to consume site map files viz., using SiteMapPath control, using SiteMap Data Source control and using SiteMap class. You can also enable role based security to the navigation links rendered using a feature called security trimming. These controls and classes together help you create a professional navigation structure for your web sites.


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Meditation and Mindfulness to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 17 August 2008


Tags : ASP.NET Web Forms Server Controls