Поделиться через


Маршрутизация в веб-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 с маршрутом, выбирает контроллер, а затем выбирает вызываемое действие.