Why is this route parameter tacked onto the querystring?

我是研究僧i 提交于 2020-01-24 03:56:04

问题


I have an ASP.NET MVC 3 application that records a user's pedometer entries. A user can view all most recent pedometer entries by visiting /Pedometer and can filter by year, year/month, or year/month/date by visiting URLs like /Pedometer/2011, /Pedometer/2011/08 and /Pedometer/2011/08/15, respectively.

I've created two mapped routes in Global.asax. The first route, shown below, is what allows the various URL patterns for filtering by date. The second route (not shown) is the default ASP.NET MVC route.

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

Here's my question. I have a view where I want to create a link of the form: currentUrl?format=csv, which will let the user download the pedometer entries for the requested URL in a CSV format. So if a user is visiting /Pedometer, the download link would be to /Pedometer?format=csv. If the user is visiting /Pedometer/2011/08 the download link would be to /Pedometer/2011/08?format=csv.

To create such a link I added a custom Html Helper named DownloadToExcel with the following code:

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
}

When I add the @Html.DownloadToExcel() markup in my view, it generates a link, but here's the rub - when the user visits the recent entries or the entries filtered by year/month or year/month/date, it works as expected, but not when the user visits the year filter URL.

The following list shows the URL the user visits and the corresponding URL generated by the custom Html Helper:

  • Visiting: /Pedometer - Download link: /Pedometer?format=csv
  • Visiting: /Pedometer/2011 - Download link: /Pedometer?year=2011&format=csv
  • Visiting: /Pedometer/2011/08 - Download link: /Pedometer/2011/08?format=csv
  • Visiting: /Pedometer/2011/08/15 - Download link: /Pedometer/2011/08/15?format=csv

Why is it when visiting /Pedometer/2011 the download link is /Pedometer?year=2011&format=csv and not /Pedometer/2011?format=csv? And why does it not work for that one case but works as expected for the year/month and year/month/date cases?

Thanks


回答1:


This problem is most likely caused by this bug described by Phil Haack on his blog. There's a regression bug introduced in ASP.NET MVC 3 when you have two consecutive optional URL parameters.




回答2:


I created a small MVC 3 application with the code you provided and got exactly the same behavior as described.

If I go to http://localhost:51181/pedometer/2011 the generated link would be http://localhost:51181/Pedometer?year=2011&format=csv.

But if I explicitly entered the name of the action (Index) it would render correctly.

Visiting http://localhost:51181/pedometer/index/2011 will generate the following link:

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

It seems the correct route is not always used by the HtmlHelper extension method.

If I add the following route just below your custom route, but before the default MVC route it works OK.

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


来源:https://stackoverflow.com/questions/7085762/why-is-this-route-parameter-tacked-onto-the-querystring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!