MVC Обычная маршрутизация и маршрутизация атрибутов не работают вместе

Я использую обычную маршрутизацию в проекте ASP.Net MVC и хотел бы включить параллельную маршрутизацию атрибутов. Я создал следующее, но я получаю 404 на обычном маршруте при включении маршрутизации атрибутов

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapMvcAttributeRoutes();

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

Контроллер

[RoutePrefix("Registration")]
public class RegistrationController : Controller
{    
    [HttpGet]
    [Route("Add/{eventId}")]
    public ActionResult Add(int eventId)
    {
    }
}

Вызов

http://localhost/Registration/Add/1

Работает при звонке

http://localhost/Registration/Add?eventId=1

Больше не работает и отвечает 404 NotFound.


person Adrian    schedule 28.04.2018    source источник
comment
Ваш контроллер называется RegistrationController, поэтому при маршрутизации на основе соглашений его маршрут: http://localhost/Registration/Add, а не http:/localhost/Register/Add   -  person Federico Dipuma    schedule 29.04.2018
comment
Извините, это опечатка и вводящая в заблуждение, я обновил код. Контроллер должен быть помечен [RoutePrefix()], тогда как раньше он был просто [Route()]   -  person Adrian    schedule 29.04.2018
comment
Возможный дубликат с использованием как атрибутивной, так и условной маршрутизации   -  person Federico Dipuma    schedule 29.04.2018
comment
Получается, что я могу использовать только одно или другое? Идея заключалась в том, чтобы сохранить обычную маршрутизацию для сохранения закладок и т. д., но постепенно переключать пользователей на ссылки на основе атрибутов.   -  person Adrian    schedule 29.04.2018
comment
Кажется, что любой прямой маршрут (действие хотя бы с одним атрибутом Route) удаляет это действие из обычного маршрута. Обходной путь может состоять в том, чтобы определить другие атрибуты Route, чтобы сохранить старое поведение.   -  person Federico Dipuma    schedule 29.04.2018


Ответы (2)


Должно работать, если вы сделаете параметр шаблона {eventId} необязательным в шаблоне маршрута.

[RoutePrefix("Registration")]
public class RegistrationController : Controller {
    //GET Registration/Add/1
    //GET Registration/Add?eventId=1
    [HttpGet]
    [Route("Add/{eventId:int?}")]
    public ActionResult Add(int eventId) {
        //...
    }
}

Причина, по которой они не работали, заключается в том, что шаблон маршрута Add/{eventId} означает, что маршрут будет совпадать только в том случае, если присутствует {eventId}, поэтому

http://localhost/Registration/Add/1

работает.

Если сделать его (eventId) необязательным eventid?, это позволит

http://localhost/Registration/Add

для работы в качестве параметра шаблона не требуется. Теперь это позволит использовать строку запроса ?eventId=1, которую таблица маршрутизации будет использовать для сопоставления аргумента параметра int eventId в действии.

http://localhost/Registration/Add?eventId=1
person Nkosi    schedule 28.04.2018
comment
Это работает для меня. Если у меня есть действие с двумя параметрами, например, public ActionResult Information(int? personId, string level = ){}, то вызов localhost:54659/Registration/Information?personId=5592 не работает. Проблема в моем RouteConfig.cs? - person Adrian; 30.04.2018
comment
@ Адриан, это действие также использует маршрутизацию атрибутов? - person Nkosi; 30.04.2018
comment
В основном каждое действие контроллера, которое работает с обычной маршрутизацией, я хотел бы расширить его, чтобы использовать параллельную маршрутизацию атрибутов. Поэтому мне нужно, чтобы старый стиль работал, пока я перевожу людей на атрибутную маршрутизацию. - person Adrian; 30.04.2018

Я также получил эту проблему. Какую версию MVC вы используете? Я столкнулся с этой проблемой с MVC в ядре asp.net. Я думаю, что это недостаток, так как если вы предоставляете атрибут маршрутизации для любого метода действия, его обычный маршрут перекрывается и больше не доступен, поэтому вы получаете ошибку 404. Чтобы это работало, вы можете предоставить другой атрибут Route для своего метода действия, как этот. Это будет работать

 [Route("Add/{eventId}")]  
 [Route("Add")]
person Rohit Manocha    schedule 29.04.2018