Почему этот маршрут MVC не работает?
-
21-08-2019 - |
Вопрос
вот два маршрута из моего файла global.asax.Я пытаюсь пойти по второму маршруту и получаю ошибку 404 по умолчанию: ресурс не найден.
Когда я удаляю первый маршрут (указанный в этом примере), он работает.
Как я могу это исправить, пожалуйста?
Фрагмент кода global.asax
// GET: /user/PureKrome/Alert/69
routes.MapRoute(
"User-Alert-Details",
"user/{displayName}/alert/{alertId}",
new { controller = "Account", action = "AlertDetails", alertId = 0 });
// GET: /user/PureKrome/Alert/create
routes.MapRoute(
"User-Alert-Create",
"user/{displayName}/alert/create",
new { controller = "Account", action = "AlertCreate" });
Решение
Ваш первый маршрут является «жадным» и с радостью примет «создать» в качестве идентификатора оповещения в последнем параметре.Похоже, что вы хотите, чтобы параметр alertId был только числовым, поэтому вам следует добавить ограничение, чтобы сообщить системе маршрутизации, что этот последний параметр должен быть числовым.
Видеть это руководство.
Например:
// GET: /user/PureKrome/Alert/69
routes.MapRoute(
"User-Alert-Details",
"user/{displayName}/alert/{alertId}",
new { controller = "Account", action = "AlertDetails", alertId = 0 },
new { alertId = @"\d+" });
// GET: /user/PureKrome/Alert/create
routes.MapRoute(
"User-Alert-Create",
"user/{displayName}/alert/create",
new { controller = "Account", action = "AlertCreate" });
Обратите внимание: вы также можете изменить порядок маршрутов на обратный, но даже если вы это сделаете, вам все равно следует включить ограничение корректности, если вы хотите, чтобы alertId всегда был числом.
Другие советы
Вы хотите, чтобы маршруты были определены наоборот, чтобы точное совпадение create
предшествует неограниченному совпадению для alertId
.Это, или вы можете добавить ограничение к alertId
как заявил Twisty Maze.
Это связано с тем, что маршрутизация пытается сопоставить маршруты сверху вниз. /user/PureKrome/Alert/create
матчи на User-Alert-Details
маршрут, как он думает create
это значение для alertId
.Переключая их, он будет соответствовать только User-Alert-Create
маршрут, если 4-й сегмент явно create
и это провалится User-Alert-Details
если это не так.
Для ясности они должны работать следующим образом:
// GET: /user/PureKrome/Alert/create
routes.MapRoute(
"User-Alert-Create",
"user/{displayName}/alert/create",
new { controller = "Account", action = "AlertCreate" });
// GET: /user/PureKrome/Alert/69
routes.MapRoute(
"User-Alert-Details",
"user/{displayName}/alert/{alertId}",
new { controller = "Account", action = "AlertDetails", alertId = 0 });
Если у вас возникла еще одна подобная проблема, попробуйте отладчик URL-адресов Фила Хаака по адресу http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Проблема в том, что вы указали значения по умолчанию для контроллера и действий в первом сопоставлении.
Теперь любой входящий запрос обрабатывается по первому маршруту: если имя контроллера отсутствует, оно заменяется значением по умолчанию, а если имя действия отсутствует, оно также заменяется значением по умолчанию.
Так что на самом деле, когда вы говорите http://localhost/SomeRouteПервый сопоставитель вступает в действие и рассматривает строку «SomeRoute» как имя контроллера, затем он не находит действие, поэтому использует указанное вами действие по умолчанию, которое в вашем примере — «AlertCreate».Итак, теперь картограф пытается найти действие под названием AlertCreate в контроллере SomeRoute.
Суть в том, что второе сопоставление не срабатывает, поскольку первое сопоставление обрабатывает все ваши запросы маршрутизации.(потому что у вас указаны значения по умолчанию)