Reputation: 729
this seems like any other question about culture or routing, but I can't figure out why this is happening.
When I try to access an [Authorize]
element without being authenticated, I'm redirected to login page with a ReturnUrl param in query string. That's perfect. (boilerplate app)
Now my problem is: if I do the same with localisation within url (from routeConfig) ie: url: "{lang}/{controller}/{action}"
, I'm being redirected a first time with this parameter, but after been passed by the base controller that redirect me to a localized route. After that, ReturnUrl is null while login page (.cshtml) is loaded...
I've loooked into lots of articles, and tried numerous tricks/options and maybe on the way I did something that's breaks everything, so here are some code:
First RouteConfig :
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 }
);
}
In 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);
}
and a bit of Login.cshtml:
@using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
...
}
I hope this is silly and there is some obvious solution you could point out to me. Otherwise, does anyone understand this? and maybe help me to fix it?
PS : if I not being clear enough or you need some more info, please comment what you need! :)
Edit : from NightOwl888's comment, I'd like to add some more questions:
_I kwow there is at least 3 major ways of handling localization (locale in query string, in route, translating the url), but is there any documented or commonly used Best Practices regarding localization and culture?
_How does the .NET framework handles the redirect to login and how does it handles the query string? (since we can not register route with query string values)
Upvotes: 1
Views: 2150
Reputation: 31
Added QueryStrings to end of Routes:
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;
}
Upvotes: 3
Reputation: 27029
Specifically tell MVC which route to use. So instead of this:
Response.RedirectToRoute(RouteData.Values);
do this:
Response.RedirectToRoute("LocalizedDefault", RouteData.Values);
Upvotes: 1