在MVC4中更改运行时的路由

时间:2012-09-28 14:29:51

标签: c# asp.net asp.net-mvc asp.net-mvc-4

目前,当我输入/ru/时,它将更改为俄语,但如果我转到/,它将显示俄语资源(意味着设置了Cookie /语言环境),但它不会重定向到/ru/。我不能真正重定向它,例如,如果用户在/en/item/32并且他将语言更改为俄语,则需要将其重定向到/ru/item/32,而不是/ru

检查Cookie的[Localization]数据注释功能

public class Localization : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.RouteData.Values["lang"] != null && !string.IsNullOrWhiteSpace(filterContext.RouteData.Values["lang"].ToString()))
        {
            // Set from route data
            var lang = filterContext.RouteData.Values["lang"].ToString();
            Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang);
        }
        else
        {
            // Set from cookie
            var cookie = filterContext.HttpContext.Request.Cookies["lang"];
            var langHeader = string.Empty;
            if (cookie != null)
            {
                langHeader = cookie.Value;
                Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);
            }
            else
            {
                // Cookie does not exist, set default
                Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
            }

            filterContext.RouteData.Values["lang"] = langHeader;
        }

        // Update cookie
        HttpCookie _cookie = new HttpCookie("lang", Thread.CurrentThread.CurrentUICulture.Name);
        _cookie.Expires = DateTime.Now.AddYears(1);
        filterContext.HttpContext.Response.SetCookie(_cookie);
        base.OnActionExecuting(filterContext);
    }
}

我的路线配置如此

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

        routes.MapRoute(
            name: "Localization",
            url: "{lang}/{controller}/{action}/{id}",
            defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new string[] { "ORMebeles.Controllers" }
        );

        /*
        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new string[] { "ORMebeles.Controllers" }
        );
        */
    }
}

那么我怎样才能将{lang}属性注入路由并使其粘在那里?

1 个答案:

答案 0 :(得分:0)

您遇到的问题是,OnActionExecuting在针对您的路由评估传入请求后运行。因此,在此方案中设置filterContext.RouteData.Values["lang"] = langHeader;无效。

关于如何设置多语言站点有一个很好的(MVC 2)示例here,尽管这个例子没有在url中使用lang变量 - 大约一半时间他们将ActionLinks设置为一个动作这会改变文化,然后重定向回到上一页。

如果你需要在URL中保留lang变量,你可以设置指向当前页面的链接,但是使用像这样的HtmlHelper来改变lang参数:

public static MvcHtmlString ChangeLanguageLink(this HtmlHelper html, string text, string lang)
{
    var currentController = html.ViewContext.RouteData.GetRequiredString("controller");
    var currentAction = html.ViewContext.RouteData.GetRequiredString("action");

    return html.ActionLink(text, currentAction, currentController, new { lang }, null);
}

这应该使用您的路线生成一个链接,该链接将用户发送到相同的操作但使用不同的lang - 并且您的Localization过滤器可以相应地设置当前文化。

如果网址中未指定lang,您需要重定向,则可以将filterContxt.Result设置为RedirectResult,其参数与上述类似。