Reputation: 11914
I've had a look at the following blog post, and implemented the code as has been laid out:
ASP.NET MVC 5 Internationalization
Without areas in my MVC5 application, it works really well. A user navigates to http://localhost
and with the default language of my browser set to Italian (it) I end up with http://localhost/it
. Perfect.
With an area registered in my application, everything breaks down. A user navigating to http://localhost
as per above ends up trying to hit http://localhost/it/myarea/Home
, which doesn't exist.
As per the referenced blog post, here's what I have:
My route configuration
namespace MyWebsite
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routing to include culture
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { culture = string.Empty, controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
My area registration
namespace MyWebsite.Areas.WindowShop
{
public class MyAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "myarea";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"myarea_default",
"{culture}/myarea/{controller}/{action}/{id}",
new { action = "Index", culture = string.Empty, id = UrlParameter.Optional }
);
}
}
}
I have a BaseController
that should inject the culture of the browser if it hasn't already been supplied in the route.
namespace MyWebsite.Code
{
public class BaseController : Controller
{
protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
{
string cultureName = RouteData.Values["culture"] as string;
if (string.IsNullOrEmpty(cultureName))
cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ? Request.UserLanguages[0] : null; // obtain it from HTTP header AcceptLanguages
// some validation
cultureName = CultureHelper.GetImplementedCulture(cultureName);
if (RouteData.Values["culture"] as string != cultureName)
{
RouteData.Values["culture"] = cultureName.ToLowerInvariant();
Response.RedirectToRoute(RouteData.Values);
}
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
return base.BeginExecuteCore(callback, state);
}
}
}
I suspect that something is getting screwed up with the routing, because we seem (with the Area enabled) to be attempting to hit a HomeController
within the area, but no controller of that name exists within that area (there is a root HomeController
).
I really don't understand why, when the area is in play, we end up trying to redirect to a controller that doesn't exist.
I'm looking to get this working, as I'd like to keep the areas, and I am also trying to avoid using cookies (I'd rather have the culture in the URL).
Upvotes: 1
Views: 2165
Reputation: 36
I had exaclty the same problem following this internationalization post and solved it by adding area = AreaName as a parameter of the default area route and area = "" as a parameter of the default route:
Area route configuration:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"myarea_default",
"{culture}/myarea/{controller}/{action}/{id}",
new { action = "Index", culture = string.Empty, area = AreaName, id = UrlParameter.Optional }
);
}
Route configuration:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routing to include culture
routes.MapRoute(
name: "DefaultWithCulture",
url: "{culture}/{controller}/{action}/{id}",
defaults: new { culture = string.Empty, controller = "Home", action = "Index", area = "", id = UrlParameter.Optional }
);
}
If you have the same controller/action in distinct areas, you must add the namespaces too.
Hope it works for you too.
Upvotes: 2
Reputation: 103
After struggling with the same Problem for some time i found an answer working for me. In your Global.asax just make sure to register the Routes before registering the Areas:
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
AreaRegistration.RegisterAllAreas();
// ...
}
Upvotes: 2