Маршрутизация атрибутов ASP.NET MVC — параметр всегда имеет значение null

Недавно столкнулся со следующей проблемой. Предположим, что у нас есть следующий контроллер с методом GET внутри:

[RoutePrefix("admin-panel")]
public class AdminPanelController : Controller
{
   [Route("places/edit/{placeId}")]
   public ActionResult EditPlace(int? placeId)
   {
     return View("EditPlace", new EditPlaceViewModel(...));
   }
}

Теперь мы можем получить доступ к этому методу по URL:

(...)/админ-панель/места/редактировать/123

Проблема в том, что параметр placeId всегда имеет значение null.

Если я изменю правило маршрутизации метода EditPlace на следующее:

[RoutePrefix("admin-panel")]
public class AdminPanelController : Controller
{
   [Route("places/{placeId}/edit")]
   public ActionResult EditPlace(int? placeId)
   {
     return View("EditPlace", new EditPlaceViewModel(...));
   }
}

Все начинает работать правильно - параметр placeId успешно передается.

Что мне здесь не хватает? Почему я не могу использовать первое решение?

Заранее спасибо!

@update

Хорошо, я пропустил, что у меня есть методы POST с теми же правилами маршрутизации, которые выглядят так:

[HttpPost]
[Route("places/edit/{placeId}")]
[MultipleSubmitButton(Name = "action", Argument = "NextEditStep")]
public ActionResult NextEditStep(int? placeId, EditPlaceViewModel model)
{
    // do some operations with posted model
    return View("EditPlace", new EditPlaceViewModel(...));
}

[HttpPost]
[Route("places/edit/{placeId}")]
[MultipleSubmitButton(Name = "action", Argument = "PreviousEditStep")]
public ActionResult PreviousEditStep(int? placeId, EditPlaceViewModel model)
{
    // do some operations with posted model
    return View("EditPlace", new EditPlaceViewModel(...));
}

Если я их закомментирую, проблема исчезнет, ​​но, честно говоря, мне это нужно из-за генерации формы. Есть ли шанс использовать эти 3 метода с одинаковыми правилами маршрутизации?

У меня есть аналогичный контроллер с аналогичными 3 методами (1 GET и 2 POSTS), но у них нет параметров маршрута. В любом случае эта маршрутизация отлично работает и ведет себя так, как ожидалось. Разница лишь в том, что у первого есть параметры маршрута, а у второго нет.


person smq93    schedule 23.03.2017    source источник
comment
Есть ли у вас какой-либо другой метод действий с этим шаблоном маршрута?   -  person Shyju    schedule 23.03.2017
comment
Спасибо за отзыв - у меня есть еще один метод GET с атрибутом [Route("places/add")] и еще один с [Route("places")].   -  person smq93    schedule 23.03.2017
comment
admin-panel/places/edit/123 должен работать в соответствии с кодом, которым вы поделились.   -  person Shyju    schedule 23.03.2017
comment
@ smq93 включите в вопрос другие действия. предоставьте минимальный воспроизводимый пример, который можно использовать для воспроизведения проблемы.   -  person Nkosi    schedule 23.03.2017
comment
Не могли бы вы попробовать с {placeId:int?} - [Route("places/edit/{placeId:int?}")]public ActionResult EditPlace(int? placeId)?   -  person Win    schedule 23.03.2017
comment
Как вы подтверждаете, что placeId является нулевым?   -  person mxmissile    schedule 23.03.2017
comment
@Nkosi Я только что обновил описание проблемы. Я подтвердил это в процессе отладки.   -  person smq93    schedule 23.03.2017
comment
@Win это ничего не меняет. Я более точно разъяснил свой случай. Посмотрите обновление, пожалуйста.   -  person smq93    schedule 24.03.2017
comment
@ smq93 smq93, можете ли вы подтвердить, что EditPlace, NextEditStep и PreviousEditStep имеют один и тот же шаблон маршрута и принадлежат одному и тому же контроллеру?   -  person Nkosi    schedule 24.03.2017
comment
@Nkosi точно, они принадлежат к одному и тому же классу контроллера AdminPanelController, и все они имеют один и тот же шаблон маршрута [Route("places/edit/{placeId}")]. Они ведут себя нормально, но параметр placeId всегда равен нулю в этих трех случаях.   -  person smq93    schedule 24.03.2017
comment
@ smq93 Ваше последнее утверждение подразумевает, что оно выполняет хотя бы одно из действий. Как вы можете выполнить индивидуальное действие и не получить конфликты маршрутов? Это самая запутанная часть всей этой проблемы для меня.   -  person Nkosi    schedule 24.03.2017
comment
@Nkosi, у вас всегда может быть один и тот же маршрут как минимум для двух действий — GET и POST. Сложность здесь в том, что я добавил атрибут MultipleSubmitButton для 2 методов POST, что позволяет мне отправлять форму по одному и тому же маршруту, но с разными действиями. Он также работает на другом контроллере, где мои методы GET и POST не имеют параметров Uri. Как я уже сказал, единственная проблема заключается в том, что параметры маршрута всегда нулевые. Просто взгляните: stackoverflow.com/a/7111222/5785985   -  person smq93    schedule 24.03.2017
comment
@ smq93, тогда это означает, что его RouteData не устанавливается. следовательно, он нулевой. Проверьте отправленные данные. Держу пари, что placeId нет в словаре. Во всех показанных примерах используется маршрутизация на основе соглашений, а не маршрутизация по атрибутам.   -  person Nkosi    schedule 24.03.2017
comment
Покажите пример отправки POST.   -  person Nkosi    schedule 24.03.2017


Ответы (2)


[Route("places/edit/{placeId: int}")]

Попробуй это

person Prateik    schedule 23.03.2017
comment
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и/или как этот код отвечает на вопрос, повышает его ценность в долгосрочной перспективе. - person manniL; 24.03.2017

В маршруте можно использовать необязательные параметры, например:

[Route("places/edit/{placeId?}")]

(изменить) https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5/#options-and-defaults

person Thowk    schedule 23.03.2017