Practical ASP.NET

Managing Menus with a Custom Menu Provider

Creating your own module for managing menus is not only ridiculously easy, but opens the door for adding any other enhancements that you can think of.

In my last column (Managing Menus), I answered a question posed by a participant in an ASP.NET class that I was teaching: How to have an item in the Web.sitemap not appear in a menu but still appear in the SiteMapPath control. For that solution, I controlled which MenuItems were added to the Menu based on a custom attribute that I added to the SiteMapNodes in the Web.sitemap file.

The problem with that solution is that the code to manage the menu must be put on every page that has a menu control. If your menus only appear on a Master Page and your site has only a single Master Page, that's not a burden. However, a better solution is to centralize your code in your own custom SiteMapProvider. It's not only a better solution, it's a cooler solution and ridiculously easy to implement.

Quick review: ASP.NET uses a "provider-based" architecture where significant functionality is delivered through snap-in/snap-out providers. These providers can be configured or even replaced through entries in the site's web.config file. I touched on sitemap providers briefly way back in 2006 in a column on customizing security. In that article, I pointed out a bug in the menu controls that was revealed when you turn on cookieless security or session management and that could be handled with a custom sitemap provider.

A sitemap provider is a class that inherits from XmlSiteMapProvider. Unlike some other provider classes (the Membership provider that's used for security) this class has no required methods -- you can pick and choose which methods on the base class you want to override.

The obvious property to override is the CurrentNode property which is called by whatever is using the provider (presumably, some kind of menu) whenever a MenuItem is required. To implement a solution that uses a SiteMapProvider, first add a Class file to your site's App_Code folder and have it inherit from XMLSitemapProvider:

Public Class PHVSiteMap
    Inherits XmlSiteMapProvider

End Class

With the class in place, for this project you then need to override the GetChildNodes method which returns the list of children for any menu item (this is also used to get the main menu items which are children of the root menu). My first step is to let the base class do all the heavy lifting by calling the base class' version of the GetChildNodes method. Now that I've retrieved the nodes that should be present, I create a new collection and transfer to it only those nodes that meet my criteria. When I'm done, I return my collection from the method:

Public Overrides Function GetChildNodes( _
     ByVal node As System.Web.SiteMapNode) As _
                System.Web.SiteMapNodeCollection
Dim smnc As SiteMapNodeCollection
Dim newSmnc As New SiteMapNodeCollection()

smnc = MyBase.GetChildNodes(node)
For Each nd As SiteMapNode In smnc
  If nd.Item("displayInMenu") <> "false" Then
                newSmnc.Add(nd)
  End If
Next

Return newSmnc
End Function

The next step is to get your site to use your provider. To do that, go into the site's Web.config and add a siteMap element. Within this element you nest a providers element which allows you to specify custom configuration for your site's SiteMapProvider. To add your new custom configuration use an add tag specifying the name attribute and the type attribute. You can put whatever you want in the name attribute but you must put the name of your Class file in the type attribute. You must also provide a siteMapFile attribute set to the name of your site map (typically, that will be Web.sitemap).

Finally, you have to tell ASP.NET to use your new configuration. There are a couple of ways to do that but I do it by adding a defaultProvider attribute to the SiteMap element, setting it to the name of my configuration.

Here's an example that creates a configuration called "CustomMenu" and uses the PHVSiteMap class I created earlier:

<siteMap defaultProvider="CustomSiteMap">
  <providers>
     <add name="CustomSiteMap"
              type="PHVSiteMap"
  siteMapFile="Web.sitemap"/>
   </providers>
</siteMap>

By moving the code to my custom SiteMapProvider I not only centralize my code, I create a class that I can use in other sites (I could even compile it in a separate class library and just reference from other projects). I also now have a base for adding other "enhancements" to the default ASP.NET menuing system.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

  • AI for GitHub Collaboration? Maybe Not So Much

    No doubt GitHub Copilot has been a boon for developers, but AI might not be the best tool for collaboration, according to developers weighing in on a recent social media post from the GitHub team.

  • Visual Studio 2022 Getting VS Code 'Command Palette' Equivalent

    As any Visual Studio Code user knows, the editor's command palette is a powerful tool for getting things done quickly, without having to navigate through menus and dialogs. Now, we learn how an equivalent is coming for Microsoft's flagship Visual Studio IDE, invoked by the same familiar Ctrl+Shift+P keyboard shortcut.

  • .NET 9 Preview 3: 'I've Been Waiting 9 Years for This API!'

    Microsoft's third preview of .NET 9 sees a lot of minor tweaks and fixes with no earth-shaking new functionality, but little things can be important to individual developers.

  • Data Anomaly Detection Using a Neural Autoencoder with C#

    Dr. James McCaffrey of Microsoft Research tackles the process of examining a set of source data to find data items that are different in some way from the majority of the source items.

  • What's New for Python, Java in Visual Studio Code

    Microsoft announced March 2024 updates to its Python and Java extensions for Visual Studio Code, the open source-based, cross-platform code editor that has repeatedly been named the No. 1 tool in major development surveys.

Subscribe on YouTube