3

I'm using MvcSiteMapProvider from Github to generate breadcrumbs in my project. I have two places where an action can be called from different controllers, and the breadcrumb has to show the calling controller.

Based on several sources (mvc 3 sitemap provider- multiple paths pointing to same node, MVCSiteMapProvider breadcrumbs incorrect parent node id, MVCSiteMapProvider Dynamic Node always returns the first node for all pages in the breadcrumbs, and external references from those articles), I have switched from using the file Mvc.sitemap to decorating my actions with MvcSiteMapNodeAttribute. I have also put the proper settings into my web.config file.

<add key="MvcSiteMapProvider_IncludeAssembliesForScan" value="Solution.Project" />
<add key="MvcSiteMapProvider_UseExternalDIContainer" value="false" />
<add key="MvcSiteMapProvider_ScanAssembliesForSiteMapNodes" value="true" />
<add key="MvcSiteMapProvider_SecurityTrimmingEnabled" value="true"/>
<add key="MvcSiteMapProvider_EnableSiteMapFile" value="false"/>

However, the breadcrumbs are not recognizing the two paths.

The nodes' attributes are, starting from the root node:

(in controller Home)
[MvcSiteMapNodeAttribute(Title = "Home", Key = "Home")]

(in controller Path1)
[MvcSiteMapNodeAttribute(Title = "Path 1", Key = "Home.Path1", ParentKey = "Home")]
[MvcSiteMapNodeAttribute(Title = "Action", Key = "Home.Path1.Action", ParentKey = "Home.Path1", Route="Home.Path1")]
[MvcSiteMapNodeAttribute(Title = "Action", Key = "Home.Path2.Action", ParentKey = "Home.Path2", Route="Home.Path2")]

(in controller Path2)
[MvcSiteMapNodeAttribute(Title = "Path 2", Key = "Home.Path2", ParentKey = "Home")]
    return RedirectToAction("Action", "Path1", new { Route = "Home.Path2" } );

No matter whether I call Action from Path1 or Path2, the breadcrumb always reads Home > Path 1 > Action.

I've been working with a co-worker on this for parts of a few days, and we're at a loss as to why the different keys and the proper routes aren't working as intended.

Community
  • 1
  • 1
Codes with Hammer
  • 788
  • 3
  • 16
  • 47

1 Answers1

1

It is not possible to use a single node or a single URL in 2 different places in the SiteMap because the first match will always win when looking up the "current" node.

However, you can work around this by using 2 different URLs (and 2 different nodes) for the same page. This can be accomplished by either adding 1 or more query string parameters to the URL (in which case both URLs will call the same action), using a second action that returns the result of the first one (not a redirect), or a more advanced way is to modify your routes so you have 2 completely different URLs pointing to the same action. Once you have fixed that problem and configured each navigation path with a unique URL and each node with a unique set of route values, it should work as expected.

Also, note that you may need to use the Attributes property to specify any custom route values (such as "id") that are part of the route you are trying to match.

Have a look at the following pages for help with this. Note that the SEO features tutorial contains a downloadable demo.

Mvcsitemapprovider Multiple paths to the single page http://www.shiningtreasures.com/post/2013/08/10/mvcsitemapprovider-4-seo-features#canonical-tag https://github.com/maartenba/MvcSiteMapProvider/wiki/Multiple-Navigation-Paths-to-a-Single-Page http://www.shiningtreasures.com/post/2013/09/02/how-to-make-mvcsitemapprovider-remember-a-user-position

If the page is Internet facing, you should also use the CanonicalTag HTML helper to ensure the search engines are aware that you meant to put the same content on 2 different URLs and you can specify which one is the "main" URL. You just need to add the CanonicalTag helper to the HEAD section of your page...

<head>
    <meta charset="utf-8" />
    <title>@Html.MvcSiteMap().SiteMapTitle() - My ASP.NET MVC Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
    <meta name="viewport" content="width=device-width" />
    @Html.MvcSiteMap().CanonicalTag()
    @Html.MvcSiteMap().MetaRobotsTag()
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>

And then specify the key of the main page for the CanonicalKey on the other(s).

[MvcSiteMapNodeAttribute(Title = "Action", Key = "Home.Path1.Action", ParentKey = "Home.Path1", Route="Home.Path1")]
[MvcSiteMapNodeAttribute(Title = "Action", Key = "Home.Path2.Action", ParentKey = "Home.Path2", Route="Home.Path2", CanonicalKey="Home.Path1.Action")]

One more thing - the Route parameter is to specify a specific route in your route configuration by name when generating the URL. But you still need to provide a route with that name to MVC that calls the action method in question. Since you didn't post your routes, it is not possible to tell if that is what you are doing in your example.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212