Почему используется неправильный маршрут?

#c# #asp.net-mvc-3 #routes

#c# #asp.net-mvc-3 #маршруты

Вопрос:

Я пытаюсь сделать то, что SO делает для своего контроллера вопросов.

  • /Posts/{id}/{title} при просмотре сообщения (имя действия не отображается)
  • /Posts/New когда вы публикуете что-то новое.
  • /Posts/Delete/10 и т.д….

У меня настроено два маршрута (ну, один, если не считать значения по умолчанию). Похоже, что все действия в Post-контроллере перенаправляются через первый.

Что это? Я, очевидно, ошибаюсь, но я не могу этого понять.

 routes.MapRoute("ViewPosts",
    "Posts/{postid}/{title}",
    new { controller = "Posts", action = "View", postid = "", title = "" });

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
  

Ответ №1:

Первый маршрут обрабатывает все ваши запросы, которые начинаются с /Posts .

Вам нужно использовать ограничения, позволяющие {postid} использовать только число:

 routes.MapRoute("ViewPosts",
    "Posts/{postid}/{title}",
    new { controller = "Posts", action = "View", postid = "", title = "" },
    new { postid= @"d " });
  

В этом случае, только если указан числовой идентификатор, этот маршрут будет обрабатывать его, в противном случае будет обрабатываться маршрут «По умолчанию».

Комментарии:

1. Что происходит /Posts с этим правилом и никаким другим? Он все равно будет соответствовать. (что может быть или не быть намерением)

2. Это правило все равно будет работать. Ограничения определяются только для {postid} параметра.

3. Спасибо, это вроде сработало. (ну, никаких ошибок не выдается). Однако теперь появляются такие действия, как /edit/10 /edit?id=10

4. Попробуйте использовать RouteLink вместо ActionLink с указанием маршрута «По умолчанию» непосредственно в нем.

Ответ №2:

Все маршруты проходят через первый, потому что вы не указали, что postid поле может быть только числовым, или определили более ранний маршрут, который будет перехватываться /Posts/New . Он передается New как postid с View действием.

Вы можете добавить это определение маршрута перед теми, которые у вас есть сейчас:

 routes.MapRoute("NewPost",
    "Posts/New",
    new{controller="Posts", action="New"});
  

Или каким бы ни был соответствующий контроллер / действие.

Комментарии:

1. Тогда мне нужно иметь маршрут для каждого другого действия в этом контроллере?

2. Может быть, только тот, который улавливает все маршруты без postid и отправляет их в действие с соответствующим именем. Например routes.MapRoute("OtherPost", "Posts/{action}/{id}", new{controller="Posts"}, new{action="^[^0-9]"}); , который будет перехватывать все URL-адреса, которые не начинаются с числа, оставляя их переходящими к существующему.