0

I have Asp.NET MVC SiteMap Provider version 4.0.

I have written a small test project that has several test Razor views. Here is MvcSite xml file that has paths defined:

 <mvcSiteMapNode title="Home - default" controller="Home" action="Index">
    <mvcSiteMapNode title="Middle - default" controller="Home" action="Middle">
      <mvcSiteMapNode title="Edit - default" controller="Home" action="Edit" key="keyForEdit">
      </mvcSiteMapNode>
    <mvcSiteMapNode title="Over - another path" controller="Home" action="Over">
      <mvcSiteMapNode title="Edit through over" controller="Home" action="Edit" canonicalKey="keyForEdit">
      </mvcSiteMapNode>
    </mvcSiteMapNode>
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</mvcSiteMap>

The idea is to reach "Edit" view from different places in application. I can go through "Middle" or through "Over" Razor view. My goal is to have different bredcrumb displays for these different paths to "Edit" view. Here is a master layout that the site is built with:

    @{
        Layout = null;
    }

    <!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>This is layout</title>
    @Html.MvcSiteMap().CanonicalTag()
</head>
<body>
    <div>Hi from Layout!</div>
    <div>@Html.MvcSiteMap().SiteMapPath()</div>
    <div>
        @RenderBody()
    </div>
</body>
</html>

Still, each time I get to "Edit" view I have "Edit - default" title inside breadcrumb. Why is this? Thank you very much for your time.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Antun Tun
  • 1,507
  • 5
  • 20
  • 38
  • possible duplicate of [Mvcsitemapprovider Multiple paths to the single page](http://stackoverflow.com/questions/19953616/mvcsitemapprovider-multiple-paths-to-the-single-page) – markpsmith May 19 '14 at 09:01

2 Answers2

2

The reason for this is because you have 2 different nodes with the exact same route signature. When this occurs the first match will always win when determining the current node (the node for the current request).

For your example, both URLs have a route that look like this.

|-----------------------------------|-----------------------------------|
|         Current Request           |          SiteMap Node             |
|-----------------------------------|-----------------------------------|
|      Key       |      Value       |      Key       |      Value       |
|-----------------------------------|-----------------------------------|
| controller     | Home             | controller     | Home             |
| action         | Edit             | action         | Edit             |
|-----------------------------------|-----------------------------------|

The problem is that there is no unique way to get to the second node, so it will never match. Also, the URL (and the route) will be the same in both cases.

In order for this to work properly, the route signature must be unique for each node even if they represent the same location. The simplest way to achieve that is to add an additional parameter to make a different route signature and different URL for one of the cases.

<mvcSiteMapNode title="Home - default" controller="Home" action="Index">
    <mvcSiteMapNode title="Middle - default" controller="Home" action="Middle">
        <mvcSiteMapNode title="Edit - default" controller="Home" action="Edit" key="keyForEdit"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Over - another path" controller="Home" action="Over">
        <mvcSiteMapNode title="Edit through over" controller="Home" action="Edit" category="path2" canonicalKey="keyForEdit"/>
    </mvcSiteMapNode>
</mvcSiteMapNode>

When using the default route, the first edit page will generate the URL /Home/Edit and the second one will generate the URL /Home/Edit?category=path2. This gives MvcSiteMapProvider enough information to tell the difference between the 2 locations because they are now unique. Here is what the second one now looks like.

|-----------------------------------|-----------------------------------|
|         Current Request           |          Default Node             |
|-----------------------------------|-----------------------------------|
|      Key       |      Value       |      Key       |      Value       |
|-----------------------------------|-----------------------------------|
| controller     | Home             | controller     | Home             |
| action         | Edit             | action         | Edit             |
| category       | path2            |                                   |   
|-----------------------------------|-----------------------------------|


|-----------------------------------|-----------------------------------|
|         Current Request           |        Another Path Node          |
|-----------------------------------|-----------------------------------|
|      Key       |      Value       |      Key       |      Value       |
|-----------------------------------|-----------------------------------|
| controller     | Home             | controller     | Home             |
| action         | Edit             | action         | Edit             |
| category       | path2            | category       | path2            |
|-----------------------------------|-----------------------------------|

So when the current request route includes category=path2, it will now match the second node when looking up the current node and fail to match the first one because of the extra parameter.

You could also arrange your routes to create URLs that conform to any scheme that you like. The only limitation is that the route for each node must be unique.

Have a look at MvcSiteMapProvider - SEO Features Tutorial for an example and downloadable demo project. Also, it might help if you review How to Make MvcSiteMapProvider Remember a User's Position if you intend to use a custom URL scheme.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Sorry, I tried but still not working. am I doing sth. wrong? I have added "category" to node "Edit through over". – Antun Tun May 21 '14 at 11:11
  • Have a look at the [demo project](https://github.com/NightOwl888/MvcSiteMapProvider-SEO-Features-Tutorial/archive/master.zip) for the SEO features tutorial. "About" and "Another About" point to the same controller action but have different breadcrumb trails. That demo uses something=1234, but it really doesn't matter how you make the URL unique as long as it is unique. – NightOwl888 May 21 '14 at 15:22
  • Inside the project it works but when I replicate on my proiject it doesn't work. I have added MVCSiteProvider 4 through NuGet, also I have added parameter to MVC sitemap xml and SiteMap.Path and CanonocalTag to the layout file. I added the line below to RouteCongfig file: MvcSiteMapProvider.Web.Mvc.XmlSiteMapController.RegisterRoutes(routes);Is there anything else? Thank you – Antun Tun May 22 '14 at 09:53
  • Could you post your routes? – NightOwl888 May 22 '14 at 12:49
  • Sure, here you go:public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); MvcSiteMapProvider.Web.Mvc.XmlSiteMapController.RegisterRoutes(routes); } } – Antun Tun May 22 '14 at 13:04
  • I don't see anything wrong. You don't need to add the XmlSiteMapController.RegisterRoutes(routes), it is done internally now, but I doubt that is the problem. Spend some time comparing the projects to see if you can spot the problem. If that doesn't work, I suggest you try [enabling debugging](http://www.shiningtreasures.com/post/2013/08/21/debugging-an-mvcsitemapprovider-configuration) to see what is going on. – NightOwl888 May 22 '14 at 15:19
  • Thank you, I will certainly try to spot the difference. I am using SiteProvider ver.4 inside vs2012, maybe that is the difference. – Antun Tun May 23 '14 at 08:34
0

You can use URL in your mvc.sitemap nodes:

<mvcSiteMapNode title="Home - default" controller="Home" action="Index">
    <mvcSiteMapNode title="Middle - default" controller="Home" action="Middle">
        <mvcSiteMapNode title="Edit - default" controller="Home" action="Edit" key="keyForEdit" url="/Home/Edit"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Over - another path" controller="Home" action="Over">
        <mvcSiteMapNode title="Edit through over" controller="Home" action="Edit" url="/Home/Edit/Path2" canonicalKey="keyForEdit"/>
    </mvcSiteMapNode>
</mvcSiteMapNode>
mjyazdani
  • 2,110
  • 6
  • 33
  • 64