Назначение нескольких маршрутов одному контроллеру или действию в ASP MVC 6

Вопрос:

Можно ли назначить два разных маршрута (с параметрами) одному и тому же контроллеру в приложении ASP.NET MVC 6?

Я пробовал:

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

Примечания:

  • Я использую ASP.NET Core 1.0 RC1.

  • Причина, по которой я хочу сделать это, хочу, чтобы api совместима со старой версией нашего мобильного приложения, использующей старый URL.

Пример:

[Produces("application/json")]
[Route("api/v2/Log")]
/// The old route is "api/LogFile" which I want to be still valid for this controller.
public class LogController : Controller {
    [HttpGet("{id}", Name = "download")]
    public IActionResult GetFile([FromRoute] Guid id) 
    {
        // ...
    }
}

В приведенном выше примере: api/LogFile/{some-guid} - старый маршрут, а api/v2/log/download/{some-guid} - новый маршрут. Мне нужно, чтобы оба маршрута вызывали одно и то же действие.

Ответы

Ответ 1

Наличие двух атрибутов маршрута на уровне контроллера отлично работает в новом приложении RC1:

[Produces("application/json")]
[Route("api/[controller]")]
[Route("api/old-log")]
public class LogController: Controller
{
    [HttpGet]
    public IActionResult GetAll()
    {
        return Json(new { Foo = "bar" });
    }
}

Оба http://localhost:62058/api/log и http://localhost:62058/api/old-log возвращают ожидаемый json. Единственное предостережение, которое я видел, это то, что вы можете установить свойства имени/порядка атрибутов в случае, если вам нужно сгенерировать URL-адрес для одного из этих действий.

Имеет 2 атрибута действия:

[Produces("application/json")]        
public class LogController : Controller
{
    [Route("api/old-log")]
    [Route("api/[controller]")]
    [HttpGet]
    public IActionResult GetAll()
    {
        return Json(new { Foo = "bar" });
    }
}

Однако вам нужно быть осторожным, имея общий маршрут на уровне контроллера и конкретный маршрут действий. В этих случаях маршрут на уровне контроллера используется как префикс и добавляется к URL-адресу (здесь есть хорошая статья об этом поведении ). Это может привести к различному набору URL-адресов, чем вы ожидали, например:

[Produces("application/json")]
[Route("api/[controller]")]
public class LogController : Controller
{
    [Route("api/old-log")]
    [Route("")]
    [HttpGet]
    public IActionResult GetAll()
    {
        return Json(new { Foo = "bar" });
    }
}

2 маршрута, которые ваше приложение будет прослушивать в последнем случае, будут http://localhost:62058/api/log и http://localhost:62058/api/log/api/old-log, так как api/log добавляется как префикс для всех маршрутов, определенных на уровне действия.

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