ASP.NET 2.0 : Using the Menu Control
by Peter A. Bromberg, Ph.D.

Peter Bromberg

" It is an interesting question how far men would retain their relative rank
if they were divested of their clothes."
-- Thoreau

ASP.NET 2.0 is fun. It's more productive, it's more powerful. It has more features. And, based on everything I've heard from the ASP.NET Team and their "ZBB" (Zero Bug Bounce) effort, you'll be able to take existing ASP.NET 1.1 apps and migrate them easily.

Of course, you'll also want to explore some of the cool new things that aren't in your existing apps. One of the most useful of the new ASP.NET 2.0 controls is the Menu Control. Once you get past the short learning curve, its easy to set up and maintain, and highly customizable.




Here we will take a look at two different ways to set up the Menu Control. One, with the default SiteMap provider using a standard Xml web.siteMap file, and the other using a SqlSiteMapProvider, an example of which was recently published by Jeff Prosise in his "Wicked Code" column in MSDN magazine.

To start off, lets create a new MasterPage to hold our menus, which provides us with a ContentPlaceHolder control that all pages deriving from our MasterPage place their content into. First the HTML code, then some notes:

<%@ Master Language="C#" AutoEventWireup="true" 
CodeFile="Default.master.cs" Inherits="_Default" %> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <style> .toolbar { font-size: 13px; font-family: Verdana; padding: 6px; filter: progid:DXImageTransform.Microsoft.Gradient
(gradientType=0,startColorStr=#ffffff,endColorStr=lightblue); } </style> <title></title> </head> <body> <form id="form1" runat="server"> <div> <asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1" Orientation="Horizontal" CssClass="toolbar" Width="96px"> <StaticMenuStyle CssClass="toolbar" /> <StaticMenuItemStyle CssClass="toolbar" /> <DynamicHoverStyle CssClass="toolbar" /> <DynamicMenuStyle CssClass="toolbar" /> </asp:Menu> &nbsp; &nbsp; <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server"
SiteMapProvider="SqlSiteMapProvider" /> <asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server"
SiteMapProvider="XmlSiteMapProvider" /> <asp:Menu ID="Menu2" runat="server" DataSourceID="SiteMapDataSource2" CssClass="toolbar"> <StaticMenuStyle CssClass="toolbar" /> <StaticMenuItemStyle CssClass="toolbar" /> <DynamicHoverStyle CssClass="toolbar" /> <DynamicMenuStyle CssClass="toolbar" /> </asp:Menu> &nbsp; &nbsp; <asp:contentplaceholder id="ContentPlaceHolder1" runat="server"> </asp:contentplaceholder> </div> </form> </body>

What I have above is a Master Page declaration, an inline CSS stylesheet we will use for our menus, two asp:Menu tags and two asp:SiteMapDataSource tags. You can get all of this by simple right-clicking your Web Site in Solution Explorer, and choosing Add New Item, then MasterPage from the Installed Templates window. You can get the menu and SiteMapDataSource controls by simply dragging them onto your new Master Page from the Toolbox.

Each Menu Control needs a SiteMapDataSource. If none is specified, the default XmlSiteMapProvider is used, and it requires a "web.siteMap" xml file which you can create by choosing Add New Item and "sitemap". The web.siteMap file structure is a nested Nodelist that looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
<siteMapNode title="Home" description="Home" url="SiteMaps.aspx?id=1"> <siteMapNode title="Sales" description="The Sales Site" url="SiteMaps.aspx?id=2"> <siteMapNode title="Customers" url="SiteMaps.aspx?id=3"/> <siteMapNode title="Products" url="SiteMaps.aspx?id=4"/>
<siteMapNode title="Futures" url="SiteMaps.aspx?id=6"/> </siteMapNode> <siteMapNode title="Research" description="The Research Site" url="SiteMaps.aspx?id=7"> <siteMapNode title="Widgets" url="SiteMaps.aspx?id=8"/> <siteMapNode title="Doodads" url="SiteMaps.aspx?id=9"/> <siteMapNode title="Thingies" url="SiteMaps.aspx?id=10" /> </siteMapNode> </siteMapNode> </siteMap>

You can see that we have a "Home" siteMapNode, and that we can nest additional siteMapNodes to get the familiar tree-like dropdown menu effect. Each node has a title, description, and url. There are other members and properties, you can get the whole story at the documentation.

Since we have more than one SiteMapDataSource, we define the providers in our web.config file like so:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
 <appSettings/>
  <connectionStrings>
    <add name="SiteMapConnectionString" connectionString=
"server=(local);database=test;user id=sa;password=;"
providerName="System.Data.SqlClient" /> </connectionStrings> <system.web> <siteMap defaultProvider="SqlSiteMapProvider" enabled="true"> <providers> <add name="SqlSiteMapProvider" type="SqlSiteMapProvider" securityTrimmingEnabled="false" connectionStringName="SiteMapConnectionString" /> <add name="XmlSiteMapProvider" type="System.Web.XmlSiteMapProvider"
siteMapFile="web.SiteMap" /> </providers> </siteMap>

Note above that we have a connection string defined specifically for our SqlSiteMapProvider, and that it is specifically referenced in the defaultProvider siteMap element. I've also added back in the XmlSiteMapProvider since it is no longer the default, and have provided the required siteMapFile="web.SiteMap" attribute for it.

In my SiteMap database table, I've defined my nodes in the familar parent - child self-referencing table format:

You can see that the Provider will simply read this out into a SqlDataReader, and create the SiteMapNodes. You can look at Prosise's code for the SqlSiteMapProvider included, and see that it is very easy to create one. This datasource is assigned to one of my menus with the DataSourceID attribute of the asp:Menu tag declaration. The rest is just choosing some of the long list of properties that can be set via the Property Sheet for the control. In this case, I've decided to add a cool 3-D like gradient by simply setting the CSSClass attribute to my "toolbar" CSS class defined in the inline stylesheet. The result, when any of the pages comes up, looks like this:

I didn't spend as much time on this as I normally would, so a lot of the kind of fine-tuning one would expect for a production app is not present. However, the downloadable zip file below includes everything you need to get started, including a SQL Script that will create the "TEST" database and SiteMap table, and populate it with what you see above. Just unzip it to the folder of your choice, run the Sql Script, and in Visual Studio.NET 2005, choose File / Open / Web Site / FileSystem and point it to your folder. The "Cassini-Meanie" built in web server will take it from there. Note that I do not have Roles Authorization enabled for this particular example, but it is extremely easy to "turn on" and integrates beautifully with Forms Authentication and similar authentication schemes.

Have fun!

 

Download the Visual Studio.NET 2005 File WebSite that accompanies this article

 

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: