AttributeRouting для исправления двух параметров с именем Id

Итак, у меня есть проект, использующий Route по умолчанию из

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Я просто столкнулся с ситуацией, описанной 7 лет назад на Совет по MVC Pro: не используйте параметр URL-адреса "id" в своих маршрутах..

У них есть отличное решение, но в данный момент я не хочу менять весь свой сайт. Я надеялся исправить свою проблему с Маршрутизация атрибутов.

Однако я не могу заставить это работать, и я получаю страницу 404 Error. (на всякий случай, если ссылка выше не работает, код подробно опишу здесь).

Подробности

В своем проекте я использую ViewModels. ViewModel (очень просто) определяется как:

public class Foo {
    public int Id { get; set; }
    ...
}

Мой BarController выглядит следующим образом:

public ActionResult Create(string id) {
    if (string.IsNullOrWhiteSpace(id)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

[HttpPost]
public ActionResult Create(string id, Foo viewModel) {
    if (string.IsNullOrWhiteSpace(id)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

Ошибка

Когда я перехожу к /Bar/Create/abc123, я прекрасно вижу свою форму. Однако когда я отправляю форму, Model.IsValid - это false. Посмотрев на окно Watch для объекта this.ModelState, я обнаружил, что сообщение об ошибке

The value 'abc123' is not valid for Id.'

Я предполагаю, что это потому, что связыватель модели пытается привязать abc123 к Id на ViewModel, который имеет int в качестве свойства Id.

Что я пробовал

Вот что я до сих пор пытался сделать на своем Controller:

[Route("Bar/Create/{aid}", Name = "FooBarRouteName")]
public ActionResult Create(string aid) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

[HttpPost]
public ActionResult Create(string aid, Foo viewModel) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

Проблема теперь в том, что когда я перехожу к /Bar/Create/abc123, я получаю страницу 404 Error и даже не могу попытаться отправить форму.

Может ли кто-нибудь указать мне правильное направление или понять, что я делаю не так? Спасибо!

Не могли бы вы переименовать свойство id в Foo?

mjwills 20.07.2018 04:32

Я был, но я хотел бы знать, как заставить это работать, если я не мог. =) Мне нравится узнавать, как решать эти вещи, а не просто их "склеивать"

RoLYroLLs 20.07.2018 04:42

stackoverflow.com/questions/2654273/… помогает?

mjwills 20.07.2018 04:43

Вам не хватает маршрута в действии POST. При использовании маршрутизации по атрибутам необходимо оформить все действия.

Nkosi 20.07.2018 04:45

@Nkosi спасибо. Я тоже добавлю его туда, если в конечном итоге пойду по этому маршруту.

RoLYroLLs 20.07.2018 04:46

Не уверен, связано ли это, что произойдет, если вы также используете HttpGetAttribute?

Christian Gollhardt 20.07.2018 04:46

@mjwills, значит, вы говорите, что я должен создать новый ViewModel, который содержит свойство Foo?

RoLYroLLs 20.07.2018 04:47

@ChristianGollhardt, я могу попробовать. Сначала тестируем решение NKosi.

RoLYroLLs 20.07.2018 04:49

@ChristianGollhardt такая же ошибка 404

RoLYroLLs 20.07.2018 04:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
9
26
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Сначала убедитесь, что маршрутизация атрибутов включена до маршрутов на основе соглашений, чтобы избежать конфликтов маршрутов.

//Attribute routing
routes.MapMvcAttributeRoutes();

//Convention-based routing
routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

Вам не хватает маршрута в действии POST.

Если вы используете маршрутизацию атрибутов, вам нужно украсить все действия на контроллере.

[HttpGet]
[Route("Bar/Create/{aid}", Name = "FooBarRouteName")] // GET Bar/Create/abc123
public ActionResult Create(string aid) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

[HttpPost]
[Route("Bar/Create/{aid}")] // POST Bar/Create/abc123
public ActionResult Create(string aid, Foo viewModel) {
    if (string.IsNullOrWhiteSpace(aid)) {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    ...
}

По-прежнему не удается получить доступ к начальной странице Bar/Create/abc123

RoLYroLLs 20.07.2018 04:50

Спасибо! Я включил его, так как у меня есть AttributeRouting на других контроллерах. Еще у меня есть HttpGetAttribute до. все тот же = /

RoLYroLLs 20.07.2018 04:55

Это работает! Я не уловил предостережения о ensure that attribute routing is enabled before convention-based routes

RoLYroLLs 20.07.2018 05:24

Дамп вопрос: Вы обновляли свои RegisterRoutes в RouteConfig?

routes.MapMvcAttributeRoutes(); // should be the first call

Также убедитесь, что вы звоните выше, прежде чем регистрировать маршруты по умолчанию. Это потому, что первая конфигурация соответствует первой, когда маршрутизатор разрешает маршрут.

Также вам необходимо убедиться, что у вас правильный порядок в global.asax, если вы используете области:

RouteConfig.RegisterRoutes(RouteTable.Routes); //needs to be first
AreaRegistration.RegisterAllAreas();

Как ответил Nkosi, вы также должны добавить RouteAttribute к своему другому действию и украсить свое действие GET с помощью HttpGetAttribute.

Это вызов выше routes.MapRoute? @RoLYroLLs

Christian Gollhardt 20.07.2018 05:06

Это твоя проблема @RoLYroLLs

Christian Gollhardt 20.07.2018 05:10

я просто внимательнее замечаю ваше решение. собираюсь попробовать.

RoLYroLLs 20.07.2018 05:10

@RoLYroLLs важен порядок добавления маршрутов. Маршруты с атрибутами должны быть зарегистрированы до маршрутов на основе соглашений.

Nkosi 20.07.2018 05:16

Ух ты! Это сработало! Я собираюсь протестировать свои другие маршруты, чтобы убедиться, что все в порядке.

RoLYroLLs 20.07.2018 05:23

Поскольку @Nkosi ответил первым, а я не «обратил внимание» на часть «порядок важен», я дам ему принятый ответ. Спасибо за вашу помощь!

RoLYroLLs 20.07.2018 05:42

Другие вопросы по теме