Итак, у меня есть проект, использующий 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 и даже не могу попытаться отправить форму.
Может ли кто-нибудь указать мне правильное направление или понять, что я делаю не так? Спасибо!
Я был, но я хотел бы знать, как заставить это работать, если я не мог. =) Мне нравится узнавать, как решать эти вещи, а не просто их "склеивать"
stackoverflow.com/questions/2654273/… помогает?
Вам не хватает маршрута в действии POST. При использовании маршрутизации по атрибутам необходимо оформить все действия.
@Nkosi спасибо. Я тоже добавлю его туда, если в конечном итоге пойду по этому маршруту.
Не уверен, связано ли это, что произойдет, если вы также используете HttpGetAttribute?
@mjwills, значит, вы говорите, что я должен создать новый ViewModel, который содержит свойство Foo?
@ChristianGollhardt, я могу попробовать. Сначала тестируем решение NKosi.
@ChristianGollhardt такая же ошибка 404





Сначала убедитесь, что маршрутизация атрибутов включена до маршрутов на основе соглашений, чтобы избежать конфликтов маршрутов.
//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
Спасибо! Я включил его, так как у меня есть AttributeRouting на других контроллерах. Еще у меня есть HttpGetAttribute до. все тот же = /
Это работает! Я не уловил предостережения о ensure that attribute routing is enabled before convention-based routes
Дамп вопрос: Вы обновляли свои 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
Это твоя проблема @RoLYroLLs
я просто внимательнее замечаю ваше решение. собираюсь попробовать.
@RoLYroLLs важен порядок добавления маршрутов. Маршруты с атрибутами должны быть зарегистрированы до маршрутов на основе соглашений.
Ух ты! Это сработало! Я собираюсь протестировать свои другие маршруты, чтобы убедиться, что все в порядке.
Поскольку @Nkosi ответил первым, а я не «обратил внимание» на часть «порядок важен», я дам ему принятый ответ. Спасибо за вашу помощь!
Не могли бы вы переименовать свойство
idвFoo?