2010-12-30 16 views
7

Tengo problemas con una restricción específica que estoy tratando de configurar en una ruta. Mi URL debe tener el siguiente aspecto: http://hostname/id-my-title-can-be-that-long donde id está compuesta solo con un dígito y el título es un carácter en minúsculas con un separador de guiones. La identificación y el título también están separados por un guion. Por ejemplo: http://hostname/123-my-title.restricción de ruta regex ASP.NET MVC

Aquí es mi definición de rutas:

routes.MapRoute(
    "Test", 
    "{id}-{title}", 
    new { controller = "Article", action = "Index" }, 
    new { id = @"(\d)+", title = @"([a-z]+-?)+" } 
); 

La URL se genera correctamente con el ayudante del html:

<%: Html.ActionLink("My link", "Index", "Article", new { id = Model.IdArticle, title = Model.UrlTitle }, null) %> 

donde, por supuesto, Model.IdArticle es un Int32 y un Model.UrlTitle cadena preformada de mi título que coincida con mis requisitos (minúsculas solamente, espacio reemplazado por guiones).

El problema es que, cuando sigo el enlace, no se llama al método & controlador correcto, se cae a la siguiente ruta que es incorrecta.

Para los registros, estoy en ASP.NET MVC 2.

Cualquier persona tiene una idea?

Gracias de antemano, Fabian

+0

Finalmente, separaremos la ID del título con una calificación incorrecta. Aún me estoy preguntando por qué esto no funciona, pero ya no está bloqueando. ¡Gracias por tu ayuda! –

Respuesta

0

Usted podría tratar de pasar toda la cadena de ruta "{id} - {title}" y analizar la cadena manualmente a sí mismo antes de que llegue a su acción de hacer algo similar a Phil Haack de slug to id actionfilter attribute - link

Espero que esto ayude.

+0

Leí esa publicación de blog antes, pero me parece excesiva cuando pude dividir la información de la ruta. Como mi URL se puede crear a partir de la ruta pero no se resuelve como una ruta, estoy pensando en algún tipo de error en MVC. –

+0

Ah, es suficiente. Tendremos otro pensamiento :-) – WestDiscGolf

0

Varios caracteres en la ruta son "especiales" y dividirán los parámetros como - y /. Puede ser que los extra -s en la ruta estén haciendo que falle. Pruebe "{id}-{*title}" ya que esto hace que el título incluya todo lo que sigue.

actualización

La respuesta anterior es lo que sucede cuando se va de Stackoverflow antes de haber tenido suficiente café.

Nos encontramos con el mismo problema al tratar con nombres de archivo para archivos cargados por usuarios, la ruta incluye '-' como delimitador pero también podría usarse en el parámetro posterior, podría generar la URL correcta pero no No lo iguale. Al final escribí una clase SpecialFileRoute para manejar este problema y registré esta ruta. Aunque es un poco feo pero cumple su función.

Tenga en cuenta que mantuve en el estilo antiguo la ruta MVC para generar la URL, estaba jugando con esto para hacerlo correctamente pero es algo de lo que volveré más adelante.

/// <summary> 
/// Special route to handle hyphens in the filename, a catchall parameter in the commented route caused exceptions 
/// </summary> 
public class SpecialFileRoute : RouteBase, IRouteWithArea 
{ 
    public string Controller { get; set; } 
    public string Action { get; set; } 
    public IRouteHandler RouteHandler = new MvcRouteHandler(); 
    public string Area { get; private set; } 

    //Doc/{doccode} - {CatNumber}.{version} - {*filename}, 

    public SpecialFileRoute(string area) 
    { 
     Area = area; 
    } 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
     string url = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2); 
     var urlmatch = Regex.Match(url, @"doc/(\w*) - (\d*).(\d*) - (.*)", RegexOptions.IgnoreCase); 
     if (urlmatch.Success) 
     { 
      var routeData = new RouteData(this, this.RouteHandler); 

      routeData.Values.Add("doccode", urlmatch.Groups[1].Value); 
      routeData.Values.Add("CatNumber", urlmatch.Groups[2].Value); 
      routeData.Values.Add("version", urlmatch.Groups[3].Value); 
      routeData.Values.Add("filename", urlmatch.Groups[4].Value); 
      routeData.Values.Add("controller", this.Controller); 
      routeData.Values.Add("action", this.Action); 
      return routeData; 
     } 
     else 
      return null; 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
     if (values.ContainsKey("controller") && (!string.Equals(Controller, values["controller"] as string, StringComparison.InvariantCultureIgnoreCase))) 
      return null; 
     if (values.ContainsKey("action") && (!string.Equals(Action, values["action"] as string, StringComparison.InvariantCultureIgnoreCase))) 
      return null; 
     if ((!values.ContainsKey("contentUrl")) || (!values.ContainsKey("format"))) 
      return null; 
     return new VirtualPathData(this, string.Format("{0}.{1}", values["contentUrl"], values["format"])); 
    } 
} 

Se añade la ruta de la siguiente manera:

context.Routes.Add(new SpecialFileRoute(AreaName) { Controller = "Doc", Action = "Download" }); 

Como se ha dicho anteriormente esto es un poco feo y cuando tengo tiempo hay una gran cantidad de trabajo que me gustaría hacer para mejorar esto, pero Resolvió el problema de dividir la URL en los parámetros necesarios. Está muy ligado a los requisitos específicos de esta ruta con el patrón de URL, Regex y Values ​​codificados, aunque debería darle un comienzo.

+0

Gracias por la información, pero no podemos utilizar un parámetro catchall (*) en un segmento que contiene más de una sección. –

+0

D'oh, por supuesto. Me encontré con el mismo problema hace un tiempo – Chao

Cuestiones relacionadas