ASP.NET (MVC) routes internationalization

廉价感情. 提交于 2019-12-23 09:19:59

问题


I was looking for a solution to internationalize/localize routes on an ASP.NET MVC website. I stumbled upon the blog post Translating routes (ASP.NET MVC and Webforms) by Maarten Balliauw. He present a very nice solution, which works great - until there's a Html.RenderAction("...") in the view.

Basically he introduces a TranslatedRoute inheriting from System.Web.Routing.Route, that than does the translation using a Dictionary with the translations on the fly.

Any idea why this behaves differently when calling Html.RenderAction("...")? Also it seems like if the error only occurs, if the action that should be rendered is in the same controller.

And here's the exact error:

"The controller for path '/MyTranslatedControllerName' was not found or does not implement IController."

Update:

Here's my routes configuration (taken from Maarten's sample project, added routes for Contact, which is the partial to be rendered):

    public static void RegisterRoutes(RouteCollection routes)
        {
            CultureInfo cultureEN = CultureInfo.GetCultureInfo("en-US");
            CultureInfo cultureDE = CultureInfo.GetCultureInfo("de-DE");
            CultureInfo cultureFR = CultureInfo.GetCultureInfo("fr-FR");

            DictionaryRouteValueTranslationProvider translationProvider = new DictionaryRouteValueTranslationProvider(
                new List<RouteValueTranslation> {
                    new RouteValueTranslation(cultureEN, "Home", "Home"),
                    new RouteValueTranslation(cultureEN, "About", "About"),
                    new RouteValueTranslation(cultureEN, "Contact", "Contact"),
                    new RouteValueTranslation(cultureDE, "Home", "Home"),
                    new RouteValueTranslation(cultureDE, "About", "About"),
                    new RouteValueTranslation(cultureDE, "Contact", "Kontakt"),
                    new RouteValueTranslation(cultureFR, "Home", "Demarrer"),
                    new RouteValueTranslation(cultureFR, "About", "Infos"),
                    new RouteValueTranslation(cultureFR, "Contact", "Contact")
                }
            );

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

            routes.MapTranslatedRoute(
                "TranslatedRoute",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = "" },
                new { controller = translationProvider, action = translationProvider },
                true
            );

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

回答1:


This will depend on your route configuration. Can you share it?

EDIT: It seems the RenderAction method is using "GetVirtualPath" on the route to determine a URL for the MvcHandler. However, that one does not call back into the "GetRouteData" method.

There is a method of detecting this: routeData.DataTokens["ParentActionViewContext"] Problem is it comes to late in the pipeline for the TranslatedRoute to know about this...

In short: I'm affraid this is impossible by the current implementation of ChildActionExtensions.ActionHelper in System.Web.Mvc...

I do have a (dirty, self-disrespecting) workaround (which you can also wrap in a custom RenderAction() method): - In your view, do this:

<%
RouteData.DataTokens.Add("GoingToRenderChildAction",
true); %> <%
Html.RenderAction("Contact", "Home");
%> <%
RouteData.DataTokens["GoingToRenderChildAction"]
= false; %>

Razor syntax:

@{
    ViewContext.RequestContext.RouteData.DataTokens.Add("GoingToRenderChildAction",
                                                         true);
}

@Html.Action("Action", "Controller" )

@{
    ViewContext.RequestContext.RouteData.DataTokens["GoingToRenderChildAction"]=false;
}

In TranslatedRoute.cs GetVirtualPath, add the following as the first statement:

if(requestContext.RouteData.DataTokens.ContainsKey("GoingToRenderChildAction") &&
(bool)requestContext.RouteData.DataTokens["GoingToRenderChildAction"] == true)
{
    return base.GetVirtualPath(requestContext, values);
}

This will work, but may have unwanted side effects.




回答2:


In your view(Razor syntax, VB):

@Html.Action("Index", "Home", New With {.childAction = True})

Then in TranslatedRoute.cs GetVirtualPath as the first statement:

if (values.ContainsKey("childAction") &&
   (bool)values["childAction"] == true)
{
  return base.GetVirtualPath(requestContext, values);
}

This way is much lighter and only for a desired action.



来源:https://stackoverflow.com/questions/6221561/asp-net-mvc-routes-internationalization

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!