Маршрутизация в веб-API ASP.NET
В этой статье описывается, как веб-API ASP.NET направляет HTTP-запросы к контроллерам.
Примечание
Если вы знакомы с ASP.NET MVC, маршрутизация веб-API очень похожа на маршрутизацию MVC. Разница main заключается в том, что для выбора действия веб-API использует http-команду, а не путь URI. Вы также можете использовать маршрутизацию в стиле MVC в веб-API. В этой статье не предполагается знание ASP.NET MVC.
Таблицы маршрутизации
В веб-API ASP.NET контроллер — это класс, обрабатывающий HTTP-запросы. Открытые методы контроллера называются методами действий или просто действиями. Когда платформа веб-API получает запрос, она направляет запрос к действию.
Чтобы определить, какое действие следует вызвать, платформа использует таблицу маршрутизации. Шаблон проекта Visual Studio для веб-API создает маршрут по умолчанию:
routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Этот маршрут определяется в файле WebApiConfig.cs , который размещается в каталоге App_Start :
Дополнительные сведения о классе см. в WebApiConfig
разделе Настройка веб-API ASP.NET.
Если вы используете веб-API для локального размещения, необходимо задать таблицу маршрутизации непосредственно в объекте HttpSelfHostConfiguration
. Дополнительные сведения см. в статье Самостоятельное размещение веб-API.
Каждая запись в таблице маршрутизации содержит шаблон маршрута. Шаблон маршрута по умолчанию для веб-API — api/{controller}/{id}. В этом шаблоне api — это сегмент литерального пути, а {controller} и {id} — переменные заполнителя.
Когда платформа веб-API получает HTTP-запрос, она пытается сопоставить URI с одним из шаблонов маршрутов в таблице маршрутизации. Если маршрут не совпадает, клиент получает ошибку 404. Например, следующие URI соответствуют маршруту по умолчанию:
- /api/contacts
- /api/contacts/1
- /api/products/gizmo1
Однако следующий универсальный код ресурса (URI) не совпадает, так как в нем отсутствует сегмент API:
- /contacts/1
Примечание
Причина использования api в маршруте заключается в том, чтобы избежать конфликтов с ASP.NET маршрутизации MVC. Таким образом, вы можете настроить переход "/contacts" к контроллеру MVC, а "/api/contacts" — к контроллеру веб-API. Конечно, если вам не нравится это соглашение, вы можете изменить таблицу маршрутов по умолчанию.
После поиска соответствующего маршрута веб-API выбирает контроллер и действие:
- Чтобы найти контроллер, веб-API добавляет "Контроллер" к значению переменной {controller} .
- Чтобы найти действие, веб-API просматривает HTTP-команду, а затем ищет действие, имя которого начинается с этого имени HTTP-команды. Например, при использовании запроса GET веб-API ищет действие с префиксом Get, например GetContact или GetAllContacts. Это соглашение применяется только к командам GET, POST, PUT, DELETE, HEAD, OPTIONS и PATCH. Вы можете включить другие HTTP-команды с помощью атрибутов на контроллере. Пример этого мы увидим позже.
- Другие переменные заполнителя в шаблоне маршрута, такие как {id}, сопоставляются с параметрами действия.
Давайте рассмотрим пример. Предположим, что вы определили следующий контроллер:
public class ProductsController : ApiController
{
public IEnumerable<Product> GetAllProducts() { }
public Product GetProductById(int id) { }
public HttpResponseMessage DeleteProduct(int id){ }
}
Ниже приведены некоторые возможные HTTP-запросы, а также действие, которое вызывается для каждого из них:
HTTP-команда | Путь URI | Действие | Параметр |
---|---|---|---|
GET | api/products | GetAllProducts | (нет) |
GET | api/products/4 | GetProductById | 4 |
DELETE | api/products/4 | DeleteProduct | 4 |
POST | api/products | (нет совпадения) |
Обратите внимание, что сегмент {id} универсального кода ресурса (при наличии) сопоставляется с параметром id действия. В этом примере контроллер определяет два метода GET: один с параметром id , а второй без параметров.
Кроме того, обратите внимание, что запрос POST завершится ошибкой, так как контроллер не определяет метод "Post...".
Варианты маршрутизации
В предыдущем разделе описан базовый механизм маршрутизации для веб-API ASP.NET. В этом разделе описываются некоторые варианты.
Команды HTTP
Вместо использования соглашения об именовании для HTTP-команд можно явно указать HTTP-команду для действия, задав метод action одним из следующих атрибутов:
[HttpGet]
[HttpPut]
[HttpPost]
[HttpDelete]
[HttpHead]
[HttpOptions]
[HttpPatch]
В следующем примере FindProduct
метод сопоставляется с запросами GET:
public class ProductsController : ApiController
{
[HttpGet]
public Product FindProduct(id) {}
}
Чтобы разрешить несколько HTTP-команд для действия или http-команд, отличных от GET, PUT, POST, DELETE, HEAD, OPTIONS и PATCH, используйте [AcceptVerbs]
атрибут , который принимает список HTTP-команд.
public class ProductsController : ApiController
{
[AcceptVerbs("GET", "HEAD")]
public Product FindProduct(id) { }
// WebDAV method
[AcceptVerbs("MKCOL")]
public void MakeCollection() { }
}
Маршрутизация по имени действия
В шаблоне маршрутизации по умолчанию веб-API использует HTTP-команду для выбора действия. Однако можно также создать маршрут, в котором имя действия будет включено в URI:
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
В этом шаблоне маршрута параметр {action} присваивает имя методу действия на контроллере. При таком стиле маршрутизации используйте атрибуты, чтобы указать разрешенные HTTP-команды. Например, предположим, что контроллер имеет следующий метод:
public class ProductsController : ApiController
{
[HttpGet]
public string Details(int id);
}
В этом случае запрос GET для api/products/details/1 будет сопоставляться с методом Details
. Этот стиль маршрутизации аналогичен ASP.NET MVC и может подходить для API в стиле RPC.
Имя действия можно переопределить с помощью атрибута [ActionName]
. В следующем примере есть два действия, которые сопоставляются с api/products/thumbnail/id. Один поддерживает GET, а другой — POST:
public class ProductsController : ApiController
{
[HttpGet]
[ActionName("Thumbnail")]
public HttpResponseMessage GetThumbnailImage(int id);
[HttpPost]
[ActionName("Thumbnail")]
public void AddThumbnailImage(int id);
}
Действия, не относящиеся к
Чтобы предотвратить вызов метода в качестве действия, используйте [NonAction]
атрибут . Это сигнализирует платформе о том, что метод не является действием, даже если он в противном случае будет соответствовать правилам маршрутизации.
// Not an action method.
[NonAction]
public string GetPrivateData() { ... }
Дополнительные материалы
В этом разделе представлено общее представление о маршрутизации. Дополнительные сведения см. в статье Маршрутизация и выбор действий, в которой описывается, как платформа точно сопоставляет URI с маршрутом, выбирает контроллер, а затем выбирает вызываемое действие.