New CodePlex project: MvcSiteMap – ASP.NET MVC sitemap provider

Edit on GitHub

NavigationIf you have been using the ASP.NET MVC framework, you possibly have been searching for something like the classic ASP.NET sitemap. After you've played with it, you even found it useful! But not really flexible and easy to map to routes and controllers. To tackle that, last year, somewhere in August, I released a proof-of-concept sitemap provider for the ASP.NET MVC framework on my blog.

The blog post on sitemap provider I released back then has received numerous comments, suggestions, code snippets, … Together with Patrice Calve, we’ve released a new version of the sitemap provider on CodePlex: MvcSiteMap.

This time I’ll not dive into implementation details, but provide you with some of the features our sitemap provider erm… provides.

First things first: registering the provider

After downloading (and compiling) MvcSiteMap, you will have to add a reference to the assembly in your project. Also, you will have to register the provider in your Web.config file. Add the following code somewhere in the <system.web> section:


<siteMap defaultProvider="MvcSiteMap">
        <add name="MvcSiteMap"


We’ve just told ASP.NET to use the MvcSiteMap sitemap provider, read sitemap nodes from the Web.sitemap file, use secrity trimming and cache the nodes for 10 minutes.

Defining sitemap nodes

Defining sitemap nodes is quite easy: add a Web.sitemap file to your project and popukate it with some nodes. Here’s an example:


<?xml version="1.0" encoding="utf-8" ?>
  <mvcSiteMapNode title="Home" controller="Home" action="Index" isDynamic="true" dynamicParameters="*">
    <mvcSiteMapNode title="About Us" controller="Home" action="About" />

    <mvcSiteMapNode title="Products" controller="Products">
      <mvcSiteMapNode title="Will be replaced in controller"
                      controller="Products" action="List"
                      isDynamic="true" dynamicParameters="id"
    <mvcSiteMapNode title="Account" controller="Account">
      <mvcSiteMapNode title="Login" controller="Account" action="LogOn" />
      <mvcSiteMapNode title="Account Creation" controller="Account" action="Register" />
      <mvcSiteMapNode title="Change Password" controller="Account" action="ChangePassword" />
      <mvcSiteMapNode title="Logout" controller="Account" action="LogOff" />


Too much info? Let’s break it down. The sitemap consists of several nodes, defined by using a <mvcSiteMapNode> element. Each node can contain other nodes, as you can see in the above example. A node should also define some attributes: title and controller. Title is used by all sitemap controls of ASP.NET, controller is used to determine the controller to link to. Here’s a list of possible attributes:

titleYesTitle of the node.
controllerYesController the node should link to.
actionOptionalAction method of the specified controller the node should link to.
keyOptionalA key used to identify the node. Can be specified but is generated by the MvcSiteMap sitemap provider when left blank.
isDynamicOptionalSpecifies if this is a dynamic node (explained later)
dynamicParametersWhen isDynamic is set to true.Specifies which parameters are dynamic. Multiple can be specified using a comma (,) as separator.
visibilityOptionalWhen visibility is set to InSiteMapPathOnly, the node will not be rendered in the menu.
*OptionalAny other parameter will be considered to be an action method parameter.

Regarding the wildcard (*), here’s a sample sitemap node:


<mvcSiteMapNode title="Contact Maarten" controller="About" action="Contact" who=”Maarten” />


This node will map to the URL http://…./About/Contact/Maarten.

Using the sitemap

We can, for example, add breadcrumbs to our master page. Here’s how:


<asp:SiteMapPath ID="SiteMapPath" runat="server"></asp:SiteMapPath>


Looks exactly like ASP.NET Webforms, no?

Dynamic parameters

You got to click it, before you kick it. In the table mentioned above, you may have seen the isDynamic and dynamicParameters attributes. This may sound a bit fuzzy, but it’s actually quite a powerful feature. Consider the following sitemap node:


<mvcSiteMapNode title="Product details" controller="Product" action="Details" isDynamic=”true” dynamicParameters=”id” />


This node will actually be used by the sitemap controls when any URL refering /Products/Details/… is called:

  • http://…./Products/Details/1234
  • http://…./Products/Details/5678
  • http://…./Products/Details/9012

No need for separate sitemap nodes for each of the above URLs! One node is enough to provide your users with a consistent breadcrumb showing their location in your web application.

The MvcSiteMapNode attribute

Who said sitemaps should always be completely defined in XML? Why not use the MvcSiteMapNode attribute we created:


[MvcSiteMapNode(ParentKey="ProductsListCategory", Title="Product details", IsDynamic=true, DynamicParameters="id")]
public ActionResult Details(string id)
    // ...


We are simply telling the MvcSiteMap sitemap provider to add a child node to the node with key “ProductsListCategory” which should have the title “Product details”. Controller and action are simply determined by the sitemap provider, based on the action method this attribute is declared on. Dynamic parameters also work here, by the way.

Do you have an example?

Yes! Simply navigate to the MvcSiteMap project page on CodePlex and grab the latest source code. The sitemap provider is included as well as an example website demonstrating all features.

kick it on

This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.

Leave a Comment


67 responses

  1. Avatar for Kam
    Kam March 24th, 2009

    I like it. I'm currently working on a similar project from the other direction: I want to make the actual URLs look like the sitemap does, so I'm working with the routing engine to support hierarchical routes to a controller based on a database driven hierarchy.

    Backlinking the routes is the biggest problem with it (e.g. it breaks Html.ActionLink()) but I hope to come up with a decent solution for that.

  2. Avatar for Michael D. Hall
    Michael D. Hall March 25th, 2009

    Very cool, I had played around with your previous posting on the concept but wasn't ready to implement it. But now you saved me the trouble! Awesome, thank you!

  3. Avatar for Matthew
    Matthew March 25th, 2009

    I tried using this with the code for the tutorial on Providing Website Navigation with SiteMaps (C#) @ I keep getting exceptions on the line

    [b]var topLevelNodes = SiteMap.RootNode.ChildNodes; [/b]

    as the ChildNodes is empty/null

  4. Avatar for maartenba
    maartenba March 25th, 2009

    I'll check if I can add a custom MenuHelper on our implementation. Keep an eye on the CodePlex sources!

  5. Avatar for maartenba
    maartenba March 25th, 2009

    There you go... Check the latest source code download.

  6. Avatar for Matthew
    Matthew March 25th, 2009

    Nice menu. Quick response!!!

  7. Avatar for Alberto Ferreira
    Alberto Ferreira March 31st, 2009

    Could we use Security Trimming? How?

    - Could choose some Nodes to "not visible", so that "Menu" don't render them (because I could want to have them in my Breadcrumb and not in my Menu - don't want a Details menu item).

  8. Avatar for Matt Penner
    Matt Penner April 1st, 2009

    I don't want to be a downer but can someone explain to me the benefit of site maps? Web Forms was never my thing and now I'm loving MVC but I don't see the point of a site map. Since the site map file isn't publicly available it's not for SEO. The only examples I ever find are menus and tree layouts. If I have dynamic menus based on login, roles and context I don't think I can use a standard control that consumes a site map.

    So, again, if someone can tell me (or better yet, show me) where they have used this in a decent sized site in a practical fashion I'd love to learn more.

  9. Avatar for maartenba
    maartenba April 1st, 2009

    Yes, you can. It will recognize all [Authorize] attributes in controllers and base its list of nodes on that.

  10. Avatar for maartenba
    maartenba April 1st, 2009

    Benefit: you have one location where the structure of your site is defined for use in breadcrumbs and menus. If you want, you can also use it to generate a sitemap.xml for Google, a static sitemap page showing all nodes, ...

  11. Avatar for Alberto Ferreira
    Alberto Ferreira April 2nd, 2009

    Hi Maarten,

    Security Trimming isn't working... I have some Authorize attributes, but this nodes still showing up on your Menu Helper.


  12. Avatar for maartenba
    maartenba April 2nd, 2009

    Will check that. Keep an eye on CodePlex source code.

  13. Avatar for Alberto Ferreira
    Alberto Ferreira April 2nd, 2009

    Dear Maarten,

    Incredible how fast are you :)

    It works. Thank You a lot!

    I will try to take advantage of your good will, and request you the following features:

    - At your Helper Menu, a property to specify the starting node level (ex.: for a 2&#186 level left menu);
    - At SiteMapNode an attribute that specify if it will be visible, so that Menu Helper don't show this nodes (like I asked you before, sometimes we want that a Action Method just shows in BreadCrumb but not at Menu);
    - Generate your URL's like URL.Action() do. Sometimes, we have custom routes that don't map "directely" Controller and Action methods. For example, I have a controller "ProductsController" and a action method "CreateByFile", but my route is: "Products/Add/ByFile". If I ask URL.Action("CreateByFile", "Products") it will give me "Products/Add/ByFile". Your SiteMapProvider gives me "Products/CreateByFile" ...

    Thank you again.

  14. Avatar for maartenba
    maartenba April 2nd, 2009

    Can you add those requests on CodePlex? (http://mvcsitemap.codeplex....

    Will see what I can do.

  15. Avatar for Michael
    Michael April 20th, 2009

    This code on the real project works very slowly
    if (this.scanAssembliesForSiteMapNodes)
    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())

  16. Avatar for maartenba
    maartenba April 20th, 2009

    You can disable that when not needed. (check the example on CodePlex' Web.config file)

  17. Avatar for Michael Sommer
    Michael Sommer April 22nd, 2009


    I tried it out, and loving it, but for some reason my nodes which I add by defining '[MvcSiteMapNode( ParentKey = "FeedbackKey", Title = "Details", DynamicParameters = "id", IsDynamic = true )]' in the class is only showing the breadcrumb for only the first details page I request. Every other details page with the same path, but different id is not showing the breadcrumb. Any ideas what I do wrong?

  18. Avatar for maartenba
    maartenba April 22nd, 2009

    Have you tried the latest CodePlex sources ( The example in there does the same and does work as expected.

  19. Avatar for Michael Sommer
    Michael Sommer April 22nd, 2009

    Yep, tried it allready, but to no effect. Appearantly the currentnode is null on the details pages.
    By the way it does not work on any of the details pages now. :-(

  20. Avatar for maartenba
    maartenba April 22nd, 2009

    Can you post a bug on CodePlex site for this? Preferably with a small reproducing example.

  21. Avatar for Martin
    Martin April 24th, 2009

    If i want to make a 2 level menu. I need to use the sitemap helper? the menu helper works only for one level menu's ?
    Great work!.

  22. Avatar for maartenba
    maartenba April 24th, 2009

    Can you give an example of how that would look? You can also post this as a feature request on

  23. Avatar for charlie
    charlie April 27th, 2009

    I wish it can support following pattern if that is possible:

    In the web.config try to define provider follow this pattern:
    And in the web.config:

    <siteMap defaultProvider="default">
    <add name="MvcSiteMapDefault"
    aclModule="MvcSiteMap.Core.DefaultMvcSiteMapAclModule, MvcSiteMap.Core"/>
    <add name="MvcSiteMapAdmin"
    aclModule="MvcSiteMap.Core.DefaultMvcSiteMapAclModule, MvcSiteMap.Core"/>

    And in the code behind of maste page, call following in page_load::
    private void SetSitemap()
    if (Roles.IsUserInRole("Administrator"))
    DemoSiteMapDataSource.SiteMapProvider = "Admin";
    else if (Roles.IsUserInRole("Branch Administrator"))
    DemoSiteMapDataSource.SiteMapProvider = "BranchAdmin";
    else if (Roles.IsUserInRole("User"))
    DemoSiteMapDataSource.SiteMapProvider = "user";

    And DemoSiteMapDataSource is type of following defined in maste page:

    <asp:SiteMapDataSource ID="DemoSiteMapDataSource" runat="server" />

    And that require the MenuHelper class use SiteMapDataSource type as input.

  24. Avatar for Maarten Balliauw
    Maarten Balliauw April 28th, 2009

    Will fix that. I've created a work item for it: http://mvcsitemap.codeplex....

  25. Avatar for Jamir
    Jamir April 28th, 2009

    Great work Maarten!

    In my MVC project, I am trying to convert to MvcSitemap from SiteMap. I have different sub folders within my Controller projects, which holds the controllers. RouteRegister registers and redirects appropriately depending on the folder and subfolder.

    In my current implementation using SiteMap. I have following syntax
    <siteMapNode title="Mileage Rates" url="~/Setup/MileageRates" description="Mileage Rates" roles="*" />

    I would like to pass /SetUp/MileageRates/Index and not just MileageRates/Index. How do I do it using MVCSitemap? When I tried giving controller="Setup/MileageRates" action="Index", it fails in MvcSiteMapProvider.cs, does not recognize "Setup/MileageRates" as a controller, which is expected.

    Any suggestion?


  26. Avatar for maartenba
    maartenba April 28th, 2009

    @Jamir, simply pass in the controller name (SetUp or MileageRates I assume). MvcSiteMap will use routing to determine the correct URL here.

  27. Avatar for Jamir
    Jamir April 29th, 2009


    I have used MVC areas as subfolders under views as well as controller see blog below. More specifically I am using Sharp-Architecture.


    For my project, http://localhost:1383/MileageRates will not work, I have to specify http://localhost:1383/Setup/MileageRates instead.

    Do you see any workaround here?

    Thank you very much for your time.

  28. Avatar for maartenba
    maartenba April 29th, 2009

    What does your route table look like and what is the controller name you are trying to reach?

  29. Avatar for maartenba
    maartenba April 29th, 2009

    Just had a look at S# architecture -> specify your sitemap node with
    <mvcSiteMapNode ... area="Setup" controller="...." action="...."/>

  30. Avatar for Jamir
    Jamir April 30th, 2009


    Couple of question on how to include Authorization to menu.

    1. I have implemented my own FormAuthentication, how can I pass Roles after user logged into the system such that my [Authorize(Roles = "Superuser")] will Authorize based on user Role. After user is logged into the system, I need to some how set this Roles for the user, what is the handle.

    2. Once I have #1 working, I would like to make my menus to be invisible when user does not have particular Role for the Action that is being displayed. When the user is not logged on, menus with Role [*] can only show up all other menus to disappear.

    Thank you very much for your time and help.

  31. Avatar for maartenba
    maartenba April 30th, 2009

    You can simply enable security trimming for the site map and it will automatically take [Authorize] attributes into account.

  32. Avatar for Jamir
    Jamir May 4th, 2009

    Hi Marteen,

    I had some issue with my Authorization, I have fixed that. Now I can push my roles to MVC Context. I have source from "10098" dated April 24th.

    My Web.Config has securityTrimmingEnabled="true" entry and my Controller method has [Authorize(Roles = "Superuser")]

    Now when my user does not have the "SuperUser" role. It just shows my login screen. It does not change any behavior by removing or adding securityTrimmingEnabled="true" in Web.Config... I am missing any additional flag to set ?

    I have a second question. I have secondary menus. My primary menu should not do any work by clicking it. Similar to using SiteMapNode with BLANK URL. When I don't have any Controller or action in the definition, it assumes the higher nodes definitions, which is Home in this case and errors out with duplicate URL. Is it possible to do achieve such functionality ?

    Thank you very much for your time and help.

  33. Avatar for maartenba
    maartenba May 4th, 2009

    Jamir, that is all normal behaviour for ASP.NET (MVC)?

    Second question: you can use regular stemap nodes for that (<siteMapNode url="...">)

  34. Avatar for Jamir
    Jamir May 4th, 2009


    One the first question. I am guessing now using MVCSiteMap I cannot hide the menus which use does not have access. Is that correct?

    What is the purpose of "securityTrimmingEnabled" ?

    Thanks again.

  35. Avatar for Maarten Balliauw
    Maarten Balliauw May 4th, 2009

    Security trimming should in fact hide menu items when user is not authorized. If this is not working, can you post an issue on http://mvcsitemap.codeplex....

  36. Avatar for Jamir
    Jamir May 5th, 2009


    I have added an issue into the Please let me know, if I can provide any further information.


  37. Avatar for maartenba
    maartenba May 5th, 2009

    Will look into it. Thanks!

  38. Avatar for Neil Kilbride
    Neil Kilbride May 12th, 2009

    Great work with the MVC sitemap provider - can't seem to get localilsation working when I set enableLocalization="true" as described @ - is this a known issue/limitation?

  39. Avatar for maartenba
    maartenba May 12th, 2009

    Can you post a small sample app + issue on http://mvcsitemap.codeplex....

  40. Avatar for kamilH
    kamilH June 1st, 2009

    you shoud add
    if (!string.IsNullOrEmpty(attributes["resourceKey"]))
    ResourceKey = attributes["resourceKey"];
    to public override void Initialize(string name, NameValueCollection attributes) in Provider

  41. Avatar for maartenba
    maartenba June 2nd, 2009

    Thanks for the tip!

  42. Avatar for Germ&#225;n
    Germ&#225;n June 11th, 2009

    Hi, Maarten, nice job! However, i&#180m still not able to use localization as it is stated in msdn. I enabled localization in the sitemap file, added resourcekeys in every sitemap node and also created the resource file Web.sitemap.resx file in my App_GlobalResources folder. Am i doing something wrong? Can you post working example with localization enabled??

  43. Avatar for maartenba
    maartenba June 11th, 2009

    Working on that... You'll know when it's done :-)

  44. Avatar for Elijah Manor
    Elijah Manor June 18th, 2009

    I am working on slowly integrating MVC into an existing WebForm project.

    I was wondering if there would be a way to use your SiteMapProvider to support both controllers/actions and/or url paths?

    I was hoping to reuse the same solution across both mvc & webform.

  45. Avatar for maartenba
    maartenba June 18th, 2009

    Working on it, work item can be followed: http://mvcsitemap.codeplex....

  46. Avatar for Jules
    Jules June 27th, 2009

    Hi Maarten,

    Good work on the MVC sitemap controller. Will functionality be added to store the sitemap in a SQL table?

    Also, can the sitemap provider be used with the menu control on a master page (I need a dynamic hierarchical menu)?



  47. Avatar for maartenba
    maartenba June 29th, 2009

    Menu control should be working.

  48. Avatar for Eric
    Eric July 2nd, 2009

    Maarten, have you had any issues when the cache expires?

    Once our expires, if we return to the main page, all the sitemap nodes now only point to
    the main page. This effectively locks us on the main page.

    it reproduces when the timeout is set to 1 min, so i know it's not cookie expiriation or security thing, it's the
    sitemap Cache time.

    any hints or hlpe is appreicated.



  49. Avatar for Ronnie Overby
    Ronnie Overby July 2nd, 2009

    I know that you can pass an arbitrary route parameter to a MvcSiteMapNode by just adding an xml attribute in Web.Sitemap. I need to do this from an action method. How do you do it?

    Specifically, I need to do something like this:
    [b]((MvcSiteMapNode)SiteMap.CurrentNode.ParentNode).AddRouteParameter("id", product.Category.ID);[/b]

    I'm betting that there is a real way to do this, but I just am missing it.


  50. Avatar for maartenba
    maartenba July 2nd, 2009

    Can you post this as a feature request on http://mvcsitemap.codeplex....

  51. Avatar for maartenba
    maartenba July 2nd, 2009

    Can you post this as an issue on http://mvcsitemap.codeplex....
    Please include any steps to reproduce this behaviour.

  52. Avatar for thomas
    thomas July 28th, 2009

    hey maarten, this MVC Sitemap provider is fantastic, thank you!

    fyi, I downloaded build 23592; it seems to still have a bug where setting SiteTitle is lost. I patched this (temporarily, hopefully) by adding an override to the Title property in your MvcSiteMapNode class.
    I'll check back for updates. Many thanks again.

  53. Avatar for maartenba
    maartenba July 28th, 2009

    Can you send me that patch?

  54. Avatar for Andy McShane
    Andy McShane July 28th, 2009

    |Hi Maarten, great piece of work, thanks. Now I have all of my translated text for my site in external xml files that I load into a data dioctionary at runtime, where would be the best place for me to make a small change to your code to be able replace the text in the sitemap node with my translated text? Remeber I am not using resource files here.

  55. Avatar for Maarten
    Maarten July 28th, 2009

    That would be the MvcSiteMapNode's Title property (you can add/replace this)

  56. Avatar for Andy McShane
    Andy McShane July 28th, 2009

    Excellent, thanks.

  57. Avatar for Jonas
    Jonas August 1st, 2009

    Repeating Alberto's request for a feature "At your Helper Menu, a property to specify the starting node level (ex.: for a 2&#186 level left menu)"

    This would be a really good feature since many menus are designed in that fashion. So if you could find the time to add that feature it would be awesome :-)

  58. Avatar for maartenba
    maartenba August 7th, 2009

    It's there :-) Download the latest bits if you want to use them.

  59. Avatar for latho
    latho August 11th, 2009


    This is great stuff. And I love the way it allows to combine menus as indicated in the last comment!
    keep up the good work!!

    I am currently trying to render breadcrumbs for more "unstructured" data. I have a LOT of categories (>5000) and the depth of nodes varies greatly (from 1 to 19). Do you have any good ways of rendering/mapping stuff like that?

    For the business logic to work I really just need to pick up the last category id since all ids are unique (illustrated in the urls-below).
    So /Category/1/11/111 shall result in the same content as putting in /Category/111 except I want to render breadcrumbs as the navigation-path and not by tracking parents recursively.

    my tree is similar to this:

    cat 1 - url: /Category/1
    cat 1.1 - url: /Category/11
    cat 1.1.1 - url: /Category/111
    cat 1.1.2
    cat 2
    cat 2.1
    cat 2.2
    cat 2.2.1
    cat 2.3

  60. Avatar for Jonas
    Jonas August 24th, 2009

    Where? How? I downloaded 24982 but I can't see how to find this feature.


  61. Avatar for awattar
    awattar August 24th, 2009

    Is there any possibility to display "Home" node when we are on Home Controller, now there is an empty space.

  62. Avatar for Phunk
    Phunk September 22nd, 2009

    Hi Maarten,

    How can I render all elements in the Web.sitemap, please? I would like the whole menu tree rendered for a drop down menu:

    <ul id="menu">
    <li>Create user</li>
    <li>Manage roles</li>

    I've of course set up the Web.sitemap with the same hierarchy, but I can't find a way to render it correctly in the Masterpage.


  63. Avatar for maartenba
    maartenba September 22nd, 2009

    Check the HtmlHelper.Sitemap() method.

  64. Avatar for Mikael &#214;stberg
    Mikael &#214;stberg September 25th, 2009


    I'm having a Controller with a default action that takes a complex object as parameter and when that Action is invoked, SiteMap.CurrentNode is null, which breaks the HtmlHelper.Menu method.

    The signature of my method is: public ActionResult Index([ModelBinder(typeof (UserQueryModelBinder))] UserQuery userQuery)

    I'm trying to match this by having this in the Web.sitemap file:
    <mvcSiteMapNode title="Search" controller="Search" action="Index" isDynamic="true" dynamicParameters="*" />

    Could it be that the problem is the complex object parameter of my method?

    Any ideas..?


  65. Avatar for maartenba
    maartenba September 27th, 2009

    Hello Mikael, are you using the latest version from CodePlex? If yes, can you post an issue on the issue tracker over there? (

  66. Avatar for G
    G December 17th, 2010

    How do you use the isDynamic property? I tried and all I get is this appended to the URL in the breadcrumb:

  67. Avatar for G
    G December 17th, 2010

    fyi, I just checked out the latest source code (Change Set 54379) and only found this option in MvcSiteMap v1.0. So is this option depreciated? If it is it's a damn shame because it's extremely convenient. So I guess I have to create my own class implementing IDynamicNodeProvider in order to get parameters to show up in the breadcrumbs????