使用ActionLink的ASP MVC 3切换语言

时间:2012-02-19 09:28:06

标签: asp.net-mvc-3 localization

在ASP MVC 3项目中,我想启用语言切换。

路由定义如下:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
             "DefaultWithLanguage", // Route name
             "{language}/{controller}/{id}/{slug}", // URL with parameters
             new { language = "en", controller = "Front", action = "Details", id = UrlParameter.Optional, slug = UrlParameter.Optional } // Parameter defaults                 
         );

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

尝试切换语言(在_Layout.cshtml中)的工作原理如下:

<li>@Html.ActionLink("Spanish", ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), new { language = "es" })</li>    

而不是获得如下所示的网址(在选择西班牙语之后)

.../es/ControllerName/ActionName

我得到了这个:

.../ControllerName/ActionName?Length=11

如果我将ActionLink设置为以下(注意最后一个空参数):

<li>@Html.ActionLink("Spanish", ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString(), new { language = "es" }, null)</li>

我明白了:

 .../ControllerName/ActionName?language=es

我缺少什么? 提前谢谢!

2 个答案:

答案 0 :(得分:1)

您的路线注册DefaultWithLanguage路线注册存在一些问题。它不允许您指定{action}。这意味着此路由仅匹配Details操作(因为您已在默认值中指定它)。另一个问题是您使{id}参数可选。但那是不可能的。只有路径的 last 参数可以是可选的。在您的情况下,后跟{slug}参数。

所以有一种可能性如下:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "DefaultWithLanguage",
        "{language}/{controller}/{action}/{id}",
        new 
        { 
            language = "en", 
            controller = "Front", 
            action = "Details", 
            id = UrlParameter.Optional 
        }
    );
}

然后:

@Html.ActionLink(
    "Spanish", 
    ViewContext.RouteData.GetRequiredString("action"), 
    ViewContext.RouteData.GetRequiredString("controller"),
    new { language = "es" },
    null
)

如果您想添加{slug}参数,那么您的{id}将不再是可选的:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "DefaultWithLanguage",
        "{language}/{controller}/{action}/{id}/{slug}",
        new 
        { 
            language = "en", 
            controller = "Front", 
            action = "Details", 
            slug = UrlParameter.Optional 
        }
    );
}

然后:

@Html.ActionLink(
    "Spanish", 
    ViewContext.RouteData.GetRequiredString("action"), 
    ViewContext.RouteData.GetRequiredString("controller"),
    new { 
        language = "es", 
        id = ViewContext.RouteData.GetRequiredString("id") 
    },
    null
)

答案 1 :(得分:0)

这是达林回答的后续行动。

我想要这样的路线:

.../en/ControllerName/Id
.../en/ControllerName/Id/Slug
.../en/ControllerName

这最后一条路线引起了问题(见达林的回答)。继续获取此路由的“黑客”是定义另一个路由(第二个名为DefaultWithLanguageWithoutId):

 public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                 "DefaultWithLanguage", // Route name
                 "{language}/{controller}/{id}/{slug}", // URL with parameters
                 new { language = "en", controller = "Front", action = "Details", id = UrlParameter.Optional, slug = UrlParameter.Optional } // Parameter defaults                                                   
             );

            routes.MapRoute(
                "DefaultWithLanguageWithoutId", // Route name
                "{language}/{controller}", // URL with parameters
                new { language = "en", controller = "Front", action = "Details"} // Parameter defaults                 

            );

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );
        }

这导致代码在母版页中调整为以下

    <li>@Html.ActionLink("Deutsch", ViewContext.RouteData.Values["action"].ToString()
, ViewContext.RouteData.Values["controller"].ToString(), new { language = "de"
, id = ViewContext.RouteData.Values["id"]!=null ? ViewContext.RouteData.Values["id"].ToString():null }, null)</li>
    <li>@Html.ActionLink("English", ViewContext.RouteData.Values["action"].ToString()
, ViewContext.RouteData.Values["controller"].ToString(), new { language = "en"
, id = ViewContext.RouteData.Values["id"] != null ? ViewContext.RouteData.Values["id"].ToString() : null }, null)</li>  

完美的作品!

唯一的“缺点”是在视图中涉及一些代码(我本来希望避免),但我觉得它很值得,因为它非常简单!