Ни [Route("api/[controller]")]
, ни [ApiController]
не являются вашей реальной проблемой. Атрибут [Route]
на уровне класса контроллера указывает префикс маршрута для всех действий в этом контроллере. Когда вы снимаете его, вы возвращаетесь к стандартному маршруту в MVC, /{controller}/{action}/{id?}
.
Также важно понимать, что использование атрибутной маршрутизации переопределяет маршрут по умолчанию на уровне, к которому он применяется . Другими словами, если вы не примените Route
к своему контроллеру, то для действий там будет использоваться маршрут по умолчанию. Если вы примените к действию атрибут Route
или один из атрибутов метода HTTP, например HttpGet
, то только это отдельное действие будет использовать маршрут настраиваемого атрибута. Однако если вы примените атрибут Route
к своему контроллеру, все действия в контроллере будут использовать маршрутизацию атрибута, даже если вы явно не применяете атрибут . Поэтому важно, чтобы вы указывали каждому действию свой уникальный маршрут.
Ваша первая проблема заключается в том, что вы применили тот же маршрут к некоторым из ваших действий, что и к контроллеру. Конечным результатом является то, что маршрут для этого действия на самом деле оказывается /api/test/api/test
. Вам нужно только указать ту часть маршрута, которая идет после префикса, то есть [HttpGet("a1")]
. Если вы хотите, чтобы он был просто префиксом, без дополнительного сегмента маршрута, тогда вы просто используете пустой маршрут, то есть [HttpGet("")]
или просто [HttpGet]
. Просто убедитесь, что вы делаете это только один раз для каждого метода HTTP.
Теперь разница с применением [ApiController]
заключается в том, что, помимо прочего, он переключает привязку по умолчанию с FromForm
на FromBody
. Однако это будет применяться только к ссылочным типам в качестве параметров, например классов. Типы значений, такие как строки, будут не связаны. Поскольку вы хотите получить их из строки запроса, очевидно, вам следует добавить [FromQuery]
к ним:
[HttpGet]
public string A3([FromQuery]string p1, [FromQuery]string p2)
Наконец, у вас также есть куча дублирующих маршрутов. Как я отмечал выше, не указание маршрута - это то же самое, что указание пустого маршрута в действии, что означает, что все, что у вас есть, это префикс маршрута, установленный на контроллере. Вы должны убедиться, что каждое действие имеет уникальный маршрут, на который оно реагирует. Например, вышеприведенный метод должен иметь что-то вроде [HttpGet("a3")]
, что даст вам предполагаемый маршрут /api/test/a3?p1=test&p2=test
.