我一直在寻找ASP.NET MVC网站上的路由国际化/本地化的解决方案。我偶然发现了Maarten Balliauw的博客文章Translating routes (ASP.NET MVC and Webforms)。他提出了一个非常好的解决方案,效果很好 - 直到视图中有Html.RenderAction("...")
。
基本上他引入了TranslatedRoute
继承自System.Web.Routing.Route
,而不是使用带有翻译的词典进行翻译。
在调用Html.RenderAction("...")
时,知道为什么这种行为有所不同?此外,似乎只有错误发生,如果应该呈现的操作位于同一个控制器中。
这是确切的错误:
“未找到路径'/ MyTranslatedControllerName'的控制器或未实现IController。”
更新
这是我的路线配置(取自Maarten的示例项目,添加了Contact的路线,这是要渲染的部分路线):
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
);
答案 0 :(得分:4)
这取决于您的路线配置。你能分享一下吗?
编辑:似乎RenderAction方法在路由上使用“GetVirtualPath”来确定MvcHandler的URL。但是,那个没有回调到“GetRouteData”方法。
有一种检测方法:routeData.DataTokens [“ParentActionViewContext”] 问题是TranslatedRoute知道这个问题的时间到了晚些时候......
简而言之:我担心当前在System.Web.Mvc中实现ChildActionExtensions.ActionHelper是不可能的......
我确实有一个(脏的,自我不尊重的)解决方法(你也可以在自定义的RenderAction()方法中包装): - 在您看来,这样做:
<%
RouteData.DataTokens.Add("GoingToRenderChildAction",
true); %> <%
Html.RenderAction("Contact", "Home");
%> <%
RouteData.DataTokens["GoingToRenderChildAction"]
= false; %>
Razor语法:
@{
ViewContext.RequestContext.RouteData.DataTokens.Add("GoingToRenderChildAction",
true);
}
@Html.Action("Action", "Controller" )
@{
ViewContext.RequestContext.RouteData.DataTokens["GoingToRenderChildAction"]=false;
}
在TranslatedRoute.cs GetVirtualPath
中,添加以下内容作为第一个语句:
if(requestContext.RouteData.DataTokens.ContainsKey("GoingToRenderChildAction") &&
(bool)requestContext.RouteData.DataTokens["GoingToRenderChildAction"] == true)
{
return base.GetVirtualPath(requestContext, values);
}
此将有效,但可能会产生不必要的副作用。
答案 1 :(得分:0)
在您的视图中(Razor语法,VB):
@Html.Action("Index", "Home", New With {.childAction = True})
然后在TranslatedRoute.cs中将GetVirtualPath作为第一个语句:
if (values.ContainsKey("childAction") &&
(bool)values["childAction"] == true)
{
return base.GetVirtualPath(requestContext, values);
}
这种方式更轻,只适用于所需的操作。