2011-08-16 12 views
6

Tengo una aplicación ASP.NET MVC 3 que registra las entradas de un podómetro de un usuario. Un usuario puede ver todas las entradas de podómetro más recientes visitando /Pedometer y puede filtrar por año, año/mes o año/mes/fecha visitando URL como /Pedometer/2011, /Pedometer/2011/08 y /Pedometer/2011/08/15, respectivamente.¿Por qué este parámetro de ruta se ha añadido a la cadena de consulta?

He creado dos rutas mapeadas en Global.asax. La primera ruta, que se muestra a continuación, es lo que permite los diversos patrones de URL para filtrar por fecha. La segunda ruta (no se muestra) es la ruta ASP.NET MVC predeterminada.

routes.MapRoute(
    "PedometerEntries", // Route name 
    "Pedometer/{year}/{month}/{day}", // URL with parameters 
    new 
    { 
     controller = "Pedometer", 
     action = "Index", 
     year = UrlParameter.Optional, 
     month = UrlParameter.Optional, 
     day = UrlParameter.Optional 
    }, // Parameter defaults 
    new 
    { 
     year = @"\d{4}", 
     month = @"([012]?\d{1})?", 
     day = @"(([1-9])|([12][0-9])|(3[0-1]))?" 
    } // Parameter constraints 
); 

Aquí está mi pregunta. Tengo una vista donde quiero crear un enlace del formulario: currentUrl?format=csv, que permitirá al usuario descargar las entradas del podómetro para la URL solicitada en formato CSV. Entonces, si un usuario está visitando /Pedometer, el enlace de descarga sería /Pedometer?format=csv. Si el usuario está visitando /Pedometer/2011/08, el enlace de descarga sería /Pedometer/2011/08?format=csv.

Para crear un enlace como he añadido un HTML personalizado ayudante nombrado DownloadToExcel con el siguiente código:

public static MvcHtmlString DownloadToExcel(this HtmlHelper helper, string linkText) 
{ 
    RouteValueDictionary routeValues = helper.ViewContext.RouteData.Values; 

    // Add the format parameter to the route data collection, if needed 
    if (!routeValues.ContainsKey("format")) 
     routeValues.Add("format", "csv"); 

    return helper.ActionLink(linkText,       // Link text 
           routeValues["action"].ToString(), // Action 
           routeValues);      // Route values 
} 

Cuando agrego el marcado @Html.DownloadToExcel() en mi opinión, se genera un vínculo, pero aquí está el problema - cuando el usuario visita las entradas recientes o las entradas filtradas por año/mes o año/mes/fecha, funciona como se esperaba, pero no cuando el usuario visita la URL del filtro del año.

La siguiente lista muestra la URL que el usuario visita y la URL correspondiente generada por la costumbre HTML Ayudante:

  • Visitante: /Pedometer - Enlace de descarga: /Pedometer?format=csv
  • Visitante: /Pedometer/2011 - Enlace de descarga: /Pedometer?year=2011&format=csv
  • Visitante: /Pedometer/2011/08 - enlace de descarga: /Pedometer/2011/08?format=csv
  • Visitante: /Pedometer/2011/08/15 - enlace de descarga: /Pedometer/2011/08/15?format=csv

¿Por qué es cuando visitaba /Pedometer/2011 el enlace de descarga se /Pedometer?year=2011&format=csv y no /Pedometer/2011?format=csv? ¿Y por qué no funciona para ese caso pero funciona como se espera para los casos año/mes y año/mes/fecha?

Gracias

Respuesta

6

Este problema es muy probablemente causado por this bug descrito por Phil Haack en su blog. Hay un error de regresión introducido en ASP.NET MVC 3 cuando tiene dos parámetros de URL opcionales consecutivos.

+0

Eso lo explica, gracias por el aviso. :-) –

4

he creado una pequeña aplicación MVC 3 con el código que ya ha proporcionado y nos dieron exactamente el mismo comportamiento que se describe.

Si voy a http://localhost:51181/pedometer/2011 el enlace generado sería http://localhost:51181/Pedometer?year=2011&format=csv.

Pero si ingresé explícitamente el nombre de la acción (Índice) se procesaría correctamente.

Visitar http://localhost:51181/pedometer/index/2011 generará el siguiente enlace:

http://localhost:51181/pedometer/index/2011?format=csv

Parece la ruta correcta no siempre es utilizado por el método de extensión HtmlHelper.

Si agrego la siguiente ruta justo debajo de su ruta personalizada, pero antes de la ruta MVC predeterminada, funciona bien.

routes.MapRoute(
    "PedometerDefault", 
    "Pedometer/{year}", 
    new { controller = "Pedometer", action = "Index", 
      year = UrlParameter.Optional } 
); 
+0

Parece la misma solución recomendada por Phil Haack en la publicación del blog en la respuesta de @George Stocker. –

+0

Sí, parece tan. No sabía del error antes de eso. –

Cuestiones relacionadas