C#Dot Net Perls

ASP.NET C#
Sitemap Recursion

by Sam Allen

Problem

Explore the nodes in our ASP.NET sitemap using recursion. You have a SiteMap and a SiteMapDataSource in your ASP.NET website. There are some ways you can use it in other parts of your project. We may want the sitemap to be used to generate navigation on our site. We also want to evaluate alternatives.

C# Solution

Here I will present some skeleton code of a better-performing, more graceful solution than the TreeView or the Repeater controls in ASP.NET. You can enhance the usability and performance of your website project by manually creating the markup for a navigation control. Let's look at some alternatives first.

How can we recurse through the nodes?

We must start with a separate method. Using the SiteMapProvider, I constructed a C# class, which I put in the App_Code folder. Let's look at method that begins the recursion.

private void BeginMapTree()
{
    // Obtain a reference to the current sitemap's provider.
    SiteMapProvider map = SiteMap.Provider;

    // Begin the recursion, starting at map.RootNode and with a depth of 0.
    MapTreeBuild(map.RootNode, map, 0);
}

How can we evaluate all nodes?

The next method uses recursion to walk through all sitemap nodes, special casing nodes based on their Depth property. Nodes will be encountered in the expected, sequential order. Also, we keep track of depth in a separate parameter, which we increase on each level of recursion.

private void MapTreeBuild(SiteMapNode nodeIn, SiteMapProvider provIn, int depth)
{
    // In this example, we build up a StringBuilder containing markup for
    // a navigation sidebar.
    foreach (SiteMapNode node in provIn.GetChildNodes(nodeIn))
    {
        if (depth == 0)
        {
            // Do something different on the first level of the tree.
            _treeBuilder.AppendLine(node.Title);
        }
        else
        {
            // Here is a way to test if this node is the current node.
            string styleClass;
            if (SiteMap.CurrentNode.Equals(node))
            {
                styleClass = "activeBucket";
            }
            else
            {
                styleClass = "regularBucket";
            }

            // Do something with a regular item in the sitemap (a page). Here we simply
            // append to a StringBuilder, which stores the result.
            _treeBuilder.Append("<div>").Append(node.Title).Append("</div>");
        }
        MapTreeBuild(node, provIn, depth + 1);
    }
}

How can I make a more complete solution?

You can switch to a custom provider or data structure for your sitemap. It would also be good to use HtmlTextWriter to build your HTML. You can use custom XML in C# very easily, or do cool things with LINQ on some sitemap-like structures, too.

Conclusion

A pre-made control may be easier to begin working with, but if you have a high-traffic or critical site, your users will greatly appreciate your more responsive site. Use the recursive method presented here to custom-tailor navigation controls and eliminate heavy-weight ASP.NET controls. Finally, this implementation could be changed to use a Stack and it might be easier to deal with.

Dot Net Perls is dedicated to sharing code and knowledge. It has
© 2007-2008 Sam Allen. All rights reserved.

Ads by The Lounge