Why is this route parameter tied to the request?

I have an ASP.NET MVC 3 application that records custom pedometer entries. The user can view all the latest pedometer entries by visiting /Pedometer and can filter by year, year / month or year / month / date by visiting URLs such as /Pedometer/2011 , /Pedometer/2011/08 and /Pedometer/2011/08/15 respectively.

I created two mapped routes in Global.asax . The first route, shown below, allows you to use different URL patterns to filter by date. The second route (not shown) is the standard 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 is my question. I have a view where I want to create a form link: currentUrl?format=csv , which will allow the user to download pedometer entries for the requested URL in CSV format. Therefore, if the user visits /Pedometer , the download link will be /Pedometer?format=csv . If the user visits /Pedometer/2011/08 , the download link will be /Pedometer/2011/08?format=csv .

To create such a link, I added a custom Html Helper called 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 @Html.DownloadToExcel() markup in my view, it generates a link, but here rub - when a user visits the last records or records filtered by year / month or year / month / date, it works as expected, but not then when the user visits the URL of the year filter.

The following list shows the URL of the user’s visitor and the corresponding URL created by the Html user assistant:

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

Why, when visiting /Pedometer/2011 download link /Pedometer?year=2011&format=csv , and not /Pedometer/2011?format=csv ? And why does this not work for one case, but works as expected in the case of year / month and year / month / date?

thanks

+6
source share
2 answers

This issue is most likely caused by this error described by Phil Haack on his blog. ASP.NET MVC 3 showed a regression error when you have two consecutive optional URL parameters.

+6
source

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 will be http: // localhost: 51181 / Pedometer? Year = 2011 & format = csv .

But if I explicitly entered the name of the action (Index), it will be displayed correctly.

A visit to http: // localhost: 51181 / pedometer / index / 2011 will produce the following link:

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

It seems that 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 standard MVC route, it works fine.

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

Source: https://habr.com/ru/post/895198/


All Articles