16

¿Alguien sabe una buena solución para localizar rutas en ASP.NET MVC? Lo que me gustaría lograr es que estos dos URLs apuntan a la misma acción/recurso:Localizar/traducir rutas en ASP.NET MVC

También debería existir la posibilidad de genere las rutas de acuerdo con la cultura actual (o la predeterminada, si no hay traducciones disponibles). Alternativamente, si pudiera especificar solo una cultura para que solo uno de los dos enlaces anteriores funcione, también sería viable.

Intenté un very nice approach by Maarten Balliauw, pero desafortunadamente su solución no funciona con Html.RenderAction(...).

Por supuesto que podría simplemente añadir rutas para todas las traducciones como

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

pero que terminaría en una enorme cantidad de rutas y sería muy inflexibles. Cualquier solución mejor sería apreciada :-) Cuanto más flexible, mejor.

Respuesta

2

Esto podría ser un camino viable para administrar todas las rutas - o alguna variación de ella como la definición de las rutas en un archivo XML

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

usted todavía termina con un gran número de rutas, pero administrarlas sería mucho más fácil

+0

Esto podría simplificar la gestión de las rutas, +1. Sin embargo, como dijiste, no resuelve el problema real. – davehauser

+0

Error de página no encontrada ... –

+0

He actualizado el enlace para obtener la última versión del archivo de retorno – Beno

0

No estoy seguro de si es el enfoque correcto, al menos no la forma en que ha publicado. Debe haber algo en el URL que define la cultura, algo así como:

De lo contrario puede terminar con una dirección URL que es ambigua entre dos o más idiomas/culturas.

+0

Creo que no debería ser un problema. Una cultura debe ser elegida (ya sea por el usuario o por el sistema) que determina el idioma de las rutas. Siempre hay un solo conjunto de rutas en uso. – davehauser

+1

Incluso si esto no es un problema per se, incluir la cultura en la URL es una práctica recomendada por Google para que puedan identificar la cultura de la página. Este es uno de los 3 enfoques recomendados: los otros serían http://en.example.org/Products/Categories o http://example.co.us/Products/Categories; por supuesto, este último podría ser un costo prohibitivo. y difícil de implementar – NightOwl888

1

¡Puedes probar el impresionante proyecto AttributeRouting que acabo de encontrar! Puede obtenerlo a través del NuGet.

0

Intente utilizar una ruta personalizada. Esto es mucho más flexible que las alternativas presentadas aquí.

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; 
    } 

} 

Puede utilizar la ruta añadiéndolo directamente a su tabla de rutas en Global.asax, así:

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 
     ); 

    } 

A continuación, en la mesa de producto localizado, basta con tener un campo que contiene la ruta para buscar (sin la barra inicial). Por supuesto, no mencionó cómo está almacenando sus datos, por lo que tendrá que proponerlo por su cuenta.

Además, tendrá que manejar su localización analizándolo desde el virtualPath. DEBE estar allí de acuerdo con Google. Debe manejar la cultura inicial en función de los encabezados pasados ​​y redirigir (302) a la url de la cultura que se selecciona. Luego, el usuario debería poder cambiar el idioma, en cuyo caso puede colocarlo en una cookie para que se recuerde su preferencia. Sin embargo, los motores de búsqueda deberían poder contar la cultura desde la URL sin pasar ningún encabezado.

Esto manejará el caso de @ Html.RenderAction() a través del método GetVirtualPath(), y puede modificar la lógica si es necesario. Le recomiendo que agregue el almacenamiento en caché, ya que esto hará que cada solicitud llegue a la base de datos tal como está. La tabla de rutas se llena al inicio de la aplicación, pero cada ruta se ejecuta en cada solicitud.

Una cosa más: para manejar el escenario "ruta no coincide", simplemente devuelva nulo y el enrutador pasará a la siguiente ruta configurada. Esto le permite configurar tantas rutas personalizadas como sea necesario sin mezclar la lógica.

Cuestiones relacionadas