Почему этот параметр маршрута прикреплен к строке запроса? - PullRequest
6 голосов
/ 17 августа 2011

У меня есть приложение ASP.NET MVC 3, которое записывает записи шагомера пользователя.Пользователь может просмотреть все последние записи шагомера, посетив /Pedometer, и отфильтровать по году, году / месяцу или году / месяцу / дате, посетив URL-адреса, такие как /Pedometer/2011, /Pedometer/2011/08 и /Pedometer/2011/08/15 соответственно.

Я создал два сопоставленных маршрута в Global.asax.Первый маршрут, показанный ниже, позволяет фильтровать различные шаблоны URL по дате.Второй маршрут (не показан) является маршрутом ASP.NET MVC по умолчанию.

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

Вот мой вопрос.У меня есть представление, где я хочу создать ссылку в форме: currentUrl?format=csv, которая позволит пользователю загружать записи шагомера для запрошенного URL в формате CSV.Так что, если пользователь посещает /Pedometer, ссылка для скачивания будет /Pedometer?format=csv.Если пользователь посещает /Pedometer/2011/08, ссылка на скачивание будет /Pedometer/2011/08?format=csv.

. Чтобы создать такую ​​ссылку, я добавил специальный помощник по HTML с именем DownloadToExcel со следующим кодом:

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
}

Когда я добавляю разметку @Html.DownloadToExcel() на мой взгляд, она генерирует ссылку, но вот в чем суть - когда пользователь посещает последние записи или записи, отфильтрованные по году / месяцу или году / месяцу / дате, он работает какожидается, но не при посещении пользователем URL-адреса фильтра года.

В следующем списке показан URL-адрес, который посещает пользователь, и соответствующий URL-адрес, созданный настраиваемым помощником по HTML:

  • Visiting:/Pedometer - Ссылка для скачивания: /Pedometer?format=csv
  • Посещение: /Pedometer/2011 - Ссылка для скачивания: /Pedometer?year=2011&format=csv
  • Посещение: /Pedometer/2011/08 - Ссылка для скачивания: /Pedometer/2011/08?format=csv
  • Посещение: /Pedometer/2011/08/15 - Ссылка для скачивания: /Pedometer/2011/08/15?format=csv

Почему при посещении /Pedometer/2011 ссылка для скачивания /Pedometer?year=2011&format=csv, а не /Pedometer/2011?format=csv?И почему это не работает для этого одного случая, но работает, как ожидается, для случаев год / месяц и год / месяц / дата?

Спасибо

Ответы [ 2 ]

6 голосов
/ 17 августа 2011

Эта проблема, скорее всего, вызвана этой ошибкой , описанной Филом Хааком в его блоге. В ASP.NET MVC 3 появилась ошибка регрессии, когда у вас есть два последовательных необязательных параметра URL.

4 голосов
/ 17 августа 2011

Я создал небольшое приложение MVC 3 с предоставленным вами кодом и получил точно такое же поведение, как описано.

Если я перейду к http://localhost:51181/pedometer/2011, сгенерированная ссылка будет http://localhost:51181/Pedometer?year=2011&format=csv.

Но если бы я явно ввел имя действия (Индекс), оно бы правильно отображалось.

При посещении http://localhost:51181/pedometer/index/2011 появится следующая ссылка:

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

Кажется, правильный метод не всегда используется методом расширения HtmlHelper.

Если я добавлю следующий маршрут чуть ниже вашего пользовательского маршрута, но перед маршрутом MVC по умолчанию, он будет работать нормально.

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