16

任何人都知道一个很好的解决方案来本地化ASP.NET MVC中的路线?我想实现的是,这两个网址都指向相同的动作/资源:本地化/翻译ASP.NET MVC路线

也应该有可能性根据当前的文化生成路线(或默认值,如果没有可用的翻译)。或者,如果我只能指定一种文化,以便只有上述两个链接中的一个可以工作,那也是可行的。

我试过very nice approach by Maarten Balliauw,但是他的解决方案不幸与Html.RenderAction(...)无效。

当然我可以只添加路由所有的翻译一样

routes.MapRoute(
    "Products_Categories", 
    "Produkte/Kategorien", 
    new { controller = "Products", action = "Categories" } 
); 

但会在路线的大量最终,它会非常不易伸缩。任何更好的解决方案,将不胜感激:-)越灵活越好。

回答

2

这可能是管理所有路线的可行方法 - 或如定义在一个XML文件的路径

http://www.iansuttle.com/blog/post/ASPNET-MVC-Store-Routes-in-the-Database.aspx

你还是会最终获得了大量的它的一些变化路线,但管理他们将是一个更容易地狱

+0

这确实可以简化路线管理+1。然而,正如你所说,这并不能解决真正的问题。 – davehauser 2011-07-19 21:53:37

+0

页面未找到错误... – 2014-12-09 15:07:49

+0

我更新了链接以从wayback存档获取最新版本 – Beno 2014-12-15 23:37:07

0

我不知道这是否是正确的方法,至少不是你张贴的方式。 应该有东西在定义文化的URL,这样的:

否则,你可以用一个URL,它是两个或两个以上的语言之间暧昧结束了/文化。

+0

我认为这不应该是一个问题。必须选择一种文化(无论是由用户还是由系统),它决定了路线的语言。它始终只有一组正在使用的路线。 – davehauser 2011-07-19 21:49:03

+1

即使这本身并不是问题,包括URL中的文化是Google推荐的做法,因此他们可以识别页面的文化。这是推荐的3种方法之一 - 其他将是http://en.example.org/Products/Categories或http://example.co.us/Products/Categories-当然后者可能会导致成本过高并难以实施。 – NightOwl888 2012-12-17 12:36:39

0

尝试使用自定义路线。这比这里介绍的替代方案更加灵活。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Web.Routing; 
using System.Web; 
using System.Web.Mvc; 

public class ProductRoute : RouteBase 
{ 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     RouteData result = null; 

     string virutalPath = httpContext.Request.Url.AbsolutePath.Substring(1).ToLowerInvariant(); 

     // Call the database here to retrieve the productId based off of the virtualPath 
     var productId = Product.GetProductIdFromVirtualPath(virutalPath); 
     if (productId != Guid.Empty) 
     { 
      result = new RouteData(this, new MvcRouteHandler()); 
      result.Values["controller"] = "Product"; 
      result.Values["action"] = "Details"; 
      result.Values["id"] = productId; 
     } 

     return result; 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     VirtualPathData result = null; 
     string controller = Convert.ToString(values["controller"]); 
     string action = Convert.ToString(values["action"]); 

     if (controller == "Product") 
     { 
      string path = string.Empty; 
      if (action == "Details") 
      { 
       Guid productId = (Guid)values["id"]; 

       // Call the database here to get the Virtual Path 
       var virtualPath = Product.GetVirtualPathFromProductId(productId); 
      } 

      if (!String.IsNullOrEmpty(virtualPath)) 
      { 
       result = new VirtualPathData(this, virtualPath); 
      } 
     } 


     return result; 
    } 

} 

您可以通过直接将其添加到你的路由表在Global.asax中,像这样使用路线:

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

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


     // Add your custom route like so 
     routes.Add(new ProductRoute()); 


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

    } 

然后在您的本地化产品表,只是有一个包含路径的场,查找(不带前导斜线)。当然,你没有提到你如何存储你的数据,所以你将不得不自己想出。

另外,您需要通过将其解析出virtualPath来处理您的本地化。根据谷歌,它应该在那里。您应该根据传递的标头处理初始文化,并将(302)重定向到所选文化的网址。然后,用户应该能够切换语言,在这种情况下,您可以将它放入cookie中,以便记住它们的偏好。但是,搜索引擎应该能够通过URL告诉文化,而不通过任何标题。

这将通过GetVirtualPath()方法处理@ Html.RenderAction()的情况,并且您可以根据需要更改逻辑。我建议你添加缓存,因为这会使每个请求都按原样到达数据库。路由表在应用程序启动时填充,但每个路由都在每个请求上执行。

还有一件事 - 要处理“路由不匹配”的情况,只需返回空值,路由器就会转到下一个配置的路由。这允许您根据需要配置尽可能多的自定义路由,而无需混合逻辑。