为什么这个路由参数附加到查询字符串上?

发布于 2024-11-30 07:45:35 字数 2550 浏览 2 评论 0原文

我有一个 ASP.NET MVC 3 应用程序,用于记录用户的计步器条目。用户可以通过访问 /Pedometer 查看所有最新的计步器条目,并可以通过访问 /Pedometer/2011 等 URL 按年、年/月或年/月/日进行过滤>、/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,这将允许用户以 CSV 格式下载所请求 URL 的计步器条目。因此,如果用户访问 /Pedometer,下载链接将是 /Pedometer?format=csv。如果用户正在访问 /Pedometer/2011/08,下载链接将是 /Pedometer/2011/08?format=csv

为了创建这样的链接,我使用以下代码添加了一个名为 DownloadToExcel 的自定义 Html Helper:

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 以及自定义 Html Helper 生成的相应 URL:

  • 访问:/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?为什么它不适用于该一种情况,但对于年/月和年/月/日期情况按预期工作?

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

聽兲甴掵 2024-12-07 07:45:35

此问题很可能是由

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.

蓝眸 2024-12-07 07:45:35

我使用您提供的代码创建了一个小型 MVC 3 应用程序,并获得了与所描述的完全相同的行为。

如果我转到 http://localhost:51181/pedometer/2011 生成的链接将是 http://localhost:51181/Pedometer?year=2011&format=csv

但如果我明确输入操作的名称(索引),它将正确呈现。

访问 http://localhost:51181/pedometer/index/2011 将生成以下链接:

< a href="http://localhost:51181/pedometer/index/2011?format=csv" rel="nofollow">http://localhost:51181/pedometer/index/2011?format=csv

HtmlHelper 扩展方法似乎并不总是使用正确的路线。

如果我在自定义路由下方、默认 MVC 路由之前添加以下路由,则它可以正常工作。

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

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 }
);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文