My route:
"{lang}/{controller}/{action}/{id}"
{lang} here is: en-US, de-DE, etc
Everything works right till moment I would like to switch language. When I switch language I am loosing part of the menu.
my MenuHelperModel.chtml
@model MvcSiteMapProvider.Web.Html.Models.MenuHelperModel
@using System.Web.Mvc.Html
@using MvcSiteMapProvider.Web.Html.Models
<div class="hmenu">
<ul class="tabs">
@foreach (var node in Model.Nodes)
{
<li>@Html.DisplayFor(m => node)</li>
}
</ul>
</div>
@foreach (var node in Model.Nodes)
{
if (node.IsInCurrentPath)
{
if (node.Children.Any()) {
//Left side menu
<div class="vmenu" style="float: left;">
<ul class="tabs">
@foreach (var child in node.Children)
{
<li><a href="@child.Url">@child.Description</a></li>
}
</ul>
</div>
}
}
}
Everything works correct only for default language, for all others node.IsInCurrentPath => false. It looks like I need to override it. Could somebody give an advice how to do it? Is there any other way to resolve the problem? Or maybe I need to assign a parent somehow? But it works for default language.
You just need to set it up to force a match on the lang
parameter so it will always be copied over from the route of the current request into the RouteValues dictionary of the nodes.
<mvcSiteMapNode title="Home" controller="Home" action="Index" preservedRouteParameters="lang">
<mvcSiteMapNode title="About" controller="Home" action="About" preservedRouteParameters="lang"/>
</mvcSiteMapNode>
I suspect the reason why it is "working" for the default language is because you have set a default lang
parameter in your route. But technically, it is still failing to match with the current URL's route because you haven't balanced both sides of the equation. You have values that look like this:
|-----------------------------------|-----------------------------------|
| Current Request | SiteMap Node |
|-----------------------------------|-----------------------------------|
| Key | Value | Key | Value |
|-----------------------------------|-----------------------------------|
| controller | Home | controller | Home |
| action | Index | action | Index |
| lang | de-DE | | |
|-----------------------------------|-----------------------------------|
Which does not match because of the missing lang
key and value in the node. Adding preservedRouteParameters with the appropriate keys will copy them over from the current request before they are compared:
|-----------------------------------|-----------------------------------|
| Current Request | SiteMap Node |
|-----------------------------------|-----------------------------------|
| Key | Value | Key | Value |
|-----------------------------------|-----------------------------------|
| controller | Home | controller | Home |
| action | Index | action | Index |
| lang | de-DE | lang | de-DE |
|-----------------------------------|-----------------------------------|
Which will force a match with any value of the lang parameter. If all of the other keys and values also match, you will have a value for the CurrentNode property that is not null, which is important to get the SiteMapPath and many features of the Menu to work. It is completely up to you to balance the books either by using preservedRouteParameters or configuring a separate node for for each route value combination, but this always must be taken into consideration when using route values other than area, controller, and action.
Also, see this answer for information about setting up localization of SiteMapNode properties.