2017年10月27日 星期五

[MVC] MvcSiteMap with custom route

 MVC    MvcSiteMap    Route

Scenario


In the previous article: [MVC] MvcSiteMap with Dependency Injection, we successfully created a menu with MvcSiteMap.





If we define a custom route with extra route placeholders, such as

routes.MapRoute(
                name: "Default",
                url: "{lang}/{controller}/{action}/{id}",
                defaults: new { lang = "Default", controller = "Home", action = "Index", id = UrlParameter.Optional }
            );

Which {lang} is expected to have these values,

http://localhost:1410/EN/Home/Index
http://localhost:1410/CN/Home/Index
http://localhost:1410/ZH/Home/Index


However, the problem is that we will always get the default value for {lang} in the node’s url like the following picture from MvcSiteMap in default!




What I expect is to have the same {lang} value as the current url.





There are two ways to get this job done, let’s take a look.


Related articles





Environment


Visual Studio 2017
Microsoft Sql Server 2012
MvcSiteMapProvider.MVC5 4.6.22
MvcSiteMapProvider.MVC5.DI.Unity 4.6.22


Implement


Method 1. Update MenuNodeProvider

While we create every node in MenuNodeProvider, we also give every node a route value for key: "lang"


MenuNodeProvider.cs

DynamicNode dynamicNode = new DynamicNode()
{
    //…
};

string lang = string.Empty;

CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentCulture;
if (ci != null)
{
       switch (ci.Name.ToLower())
       {
          case "en-us":
               lang = "EN";
               break;
          case "zh-cn":
                lang = "CN";
                break;
          default:
                lang = "ZH";
                break;
        }
}
                       
dynamicNode.RouteValues.Add("lang", lang);



So that the route value will be mapped to the url pattern’s placeholders: {lang}


Method 2. Update Display template

First go to _Layout.cshtml and find the following codes.

@Html.MvcSiteMap().Menu("BootstrapMenuHelperModel", false)

Open BootstrapMenuHelperModel.cshtml, we will create a @Helper to display the current route value for {lang}.

@helper LangValue()
{
    var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;

    string lang = "Default";
    if (routeValues != null)
    {
        if (routeValues.ContainsKey("lang"))
        {
            lang = routeValues["lang"].ToString();
        }
    }

    @lang;
}


Update the url of link from

<a href="@url">

To

<a href="/@LangValue()@url">


Last, make sure that in the custom route pattern, the placeholder: {lang}, DOES NOT have a default value.
PS. If you set Area for the MVC website, update the Area’s route as well.

routes.MapRoute(
                name: "Default",
                url: "{lang}/{controller}/{action}/{id}",
                defaults: new { lang = UrlParameter.Optional, controller = "Home", action = "Index", id = UrlParameter.Optional }
            );




Reference




沒有留言:

張貼留言