Баг с роутингом в ASP.NET MVC под 4-ый .NET Framework
15 февраля 2011 - 22:57
Полгода назад я нашёл странный баг в ASP.NET MVC 2 под .NET Framework 4. Сегодня у меня наконец дошли руки разобраться в чём там дело и как это обойти.
Итак, мы имеем следующий Route:
и хотим построить Url одним из следующих способов:
Под .NET Framework 3.5 всё работает отлично, RouteUrl возвращает правильные значения. Но стоит только сменить версию .NET Framework-а на 4-ую, как обнаруживается, что первые два RouteUrl-а возвращают null. После ряда экспериментов, я пришёл к выводу, что под 4-ым .NET Framework-ом опциональным может быть только один параметр, причём последний. Поскольку такое положение вещей меня не устраивало, то я обошёл данной ограничение "в лоб", создав несколько роутов для разного количества параметров:
И соответственно Url-ы следует получать таким образом:
Решение не самое красивое, но других вариантов обойти этот странный баг я на данный момент не нашёл. На Microsoft Connect есть данный баг для ASP.NET MVC3 RC2, но никакого решения не приведено.
Итак, мы имеем следующий Route:
routes.MapRoute( "Archive", // Route name "archive/{year}/{month}/{day}", // URL with parameters new { controller = "Archive", action = "Overview", year = UrlParameter.Optional, month = UrlParameter.Optional, day = UrlParameter.Optional }, // Parameter defaults new { year = @"(\d\d\d\d)?", month = @"\d?\d?", day = @"\d?\d?" } );
Url.RouteUrl("Archive"); Url.RouteUrl("Archive", new {year = "2011"}); Url.RouteUrl("Archive", new {year = "2011", month = "10"}); Url.RouteUrl("Archive", new {year = "2011", month = "10", day = "5"});
routes.MapRoute( "Archive", // Route name "archive", // URL with parameters new { controller = "Archive", action = "Overview"); routes.MapRoute( "ArchiveYear", // Route name "archive/{year}", // URL with parameters new { controller = "Archive", action = "Overview", year = UrlParameter.Optional}, // Parameter defaults new { year = @"(\d\d\d\d)?"} ); routes.MapRoute( "ArchiveMonth", // Route name "archive/{year}/{month}", // URL with parameters new { controller = "Archive", action = "Overview", year = UrlParameter.Optional, month = UrlParameter.Optional}, // Parameter defaults new { year = @"(\d\d\d\d)?", month = @"\d?\d?"} ); routes.MapRoute( "ArchiveDay", // Route name "archive/{year}/{month}/{day}", // URL with parameters new { controller = "Archive", action = "Overview", year = UrlParameter.Optional, month = UrlParameter.Optional, day = UrlParameter.Optional }, // Parameter defaults new { year = @"(\d\d\d\d)?", month = @"\d?\d?", day = @"\d?\d?" } );
Url.RouteUrl("Archive"); Url.RouteUrl("ArchiveYear", new {year = "2011"}); Url.RouteUrl("ArchiveMonth", new {year = "2011", month = "10"}); Url.RouteUrl("ArchiveDay", new {year = "2011", month = "10", day = "5"});
if (routeValues != null) {
foreach (KeyValuePair<string, object> routeElement in GetRouteValues(routeValues)) {
mergedRouteValues[routeElement.Key] = routeElement.Value;
}
}
Похоже параметры мержатся с параметрами текущего контекста