【问题标题】:MVC 5 culture and redirect query string loses valueMVC 5 文化和重定向查询字符串失去价值
【发布时间】:2018-02-16 21:19:54
【问题描述】:

这似乎是关于文化或路线的任何其他问题,但我无法弄清楚为什么会发生这种情况。

当我尝试在未经身份验证的情况下访问 [Authorize] 元素时,我会被重定向到登录页面,并在查询字符串中使用 ReturnUrl 参数。那很完美。 (样板应用)

现在我的问题是:如果我对 url 中的本地化(来自 routeConfig)执行相同的操作,即:url: "{lang}/{controller}/{action}",我将使用此参数第一次被重定向,但在被传递之后通过 将我重定向到本地化路线的基本控制器。之后,在加载登录页面 (.cshtml) 时 ReturnUrl 为 null...

我查看了很多文章,并尝试了许多技巧/选项,也许在我做的事情破坏了一切的过程中,所以这里有一些代码:

第一个路由配置:

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

    routes.MapRoute(
       name: "LocalizedDefault",
       url: "{lang}/{controller}/{action}",
       defaults: new { lang = UrlParameter.Optional, controller = "Home", action = "Index" } ,
       constraints: new { lang = "fr-CA|en-US" }
   );

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

}

在 BaseController 中:

protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
    string cultureName = RouteData.Values["lang"] as string;
    // Attempt to read the culture cookie from Request
    if (cultureName == null)
    {
        cultureName = Request.UserLanguages != null && 
        Request.UserLanguages.Length > 0 ? 
                            Request.UserLanguages[0] :
                            null; // obtain it from HTTP header AcceptLanguages
    }

    // Validate culture name
    cultureName = CultureHelper.GetImplementedCulture(StartupMVC.SupportedLangs, cultureName);

    if (RouteData.Values["lang"] as string != cultureName)
    {
        // Force a valid culture in the URL
        RouteData.Values["lang"] = cultureName.ToLowerInvariant(); // lower case too 

        // Redirect user
        //Response.SuppressFormsAuthenticationRedirect = false;
****HERE**** 
if I comment this line, I keep returnUrl but my route 
is like {controller}/{action}/{id} => So default language   
    Response.RedirectToRoute(RouteData.Values);  
otherwise route ok {lang}/{controller}/{action}/{id} but no ReturnUrl 
    }                                                                                
    SetCurrentCultureOnThread(cultureName);
    return base.BeginExecuteCore(callback, state);
}

还有一点 Login.cshtml:

@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
        ... 
}

我希望这很愚蠢,您可以向我指出一些明显的解决方案。 否则,有人明白吗?或许能帮我解决它?

PS:如果我不够清楚或者您需要更多信息,请评论您需要什么! :)

编辑:来自 NightOwl888 的评论,我想补充一些问题:

_我知道至少有 3 种处理本地化的主要方法(查询字符串中的语言环境、路由中的区域设置、翻译 url),但是是否有任何关于本地化和文化的记录或常用的最佳实践?

_.NET 框架如何处理重定向到登录以及它如何处理查询字符串? (因为我们不能用查询字符串值注册路由)

【问题讨论】:

  • 这种方法的问题太多,这里就不一一列举了。请参阅ASP.NET MVC 5 culture in route and url 并确保阅读有关将用户自动重定向到他们的文化的 cmets。
  • 感谢您的评论。我看到了这个答案,我认为对于现在必须广泛使用的东西来说它有点复杂......因为你似乎对这个主题了解很多,我很想知道更多,我会补充我的问题一些额外的问题,因为它可能对其他人很有价值。
  • MVC 没有内置任何东西可以让它跳过本地化的路由并转到非本地化的路由(不诉诸 302 重定向)。事实上,根本没有用于 URL 本地化的内置扩展 - 唯一的选择是自定义或使用第 3 方。但是,我不能强调让请求一直到控制器然后重定向到另一个控制器是多么糟糕。重定向有一个的目的 - 更改浏览器中的 URL。路由的目的是让第一个请求直接发送到正确的控制器,无需第二个请求。
  • 顺便说一句 - 上面的链接是我对 SO 的最高投票答案。它不是那样的,因为它对人们来说太复杂了。它实际上是复制、粘贴和配置的 2 个类,以及对视图的一些修改,以允许用户切换文化。只有在需要本地化属性路由时才需要属性路由代码。

标签: asp.net-mvc asp.net-mvc-5 culture redirecttoroute


【解决方案1】:

在路由末尾添加了查询字符串:

if (cultureOnUrl.ToLower() != culture.ToLower())
        {
            try
            {
                var routes = new RouteValueDictionary(filterContext.RouteData.Values);
                foreach (string key in filterContext.HttpContext.Request.QueryString.Keys)
                {
                    routes[key] = filterContext.HttpContext.Request.QueryString[key];
                }
                if (!routes.ContainsKey("lang"))
                    routes.Add("lang", culture);
                else
                    routes["lang"] = culture;  
           filterContext.HttpContext.Response.RedirectToRoute("LocalizedDefault",routes);     
            }
            catch (Exception ex)
            {

            }
            return;
        }

【讨论】:

    【解决方案2】:

    具体告诉 MVC 使用哪个路由。所以不要这样:

    Response.RedirectToRoute(RouteData.Values);
    

    这样做:

    Response.RedirectToRoute("LocalizedDefault", RouteData.Values);
    

    【讨论】:

    • @Minus 请更具体一些。什么不起作用?你有错误吗?
    • 我使用路由名称(在我的情况下为 'LocalizedDefault' )并不能解决问题,因为在重定向到该路由后 returnUrl 仍然为 null。
    • @Minus RouteData.Values 中的值是多少?请在进行重定向之前检查调试器。
    • 在调用 rediretToRoute 之前的 RouteData.Values 是:Account、Login 和 en-US。
    • @Minus 这就是问题所在。您需要在调用重定向之前执行此操作:RouteData.Values.Add("returnUrl", "whatever...");
    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 2015-12-16
    • 2011-01-30
    • 1970-01-01
    • 2016-03-17
    • 2011-12-12
    • 2011-02-17
    • 2016-06-03
    相关资源
    最近更新 更多