Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
За сопоставление запросов с определенными маршрутами, как и в MVC, отвечает система маршрутизации. Ключевым классом для системы маршрутизации является класс HttpRoutingDispatcher, который обрабатывает запрос для получения данных маршрута и добавляет эти данные в коллекцию HttpRequestContext.RouteData.
Другим ключевым типом является интерфейс IHttpRoute, который описывает маршрут. Web API предоставляет встроенную реализацию этого интерфейса в виде класса HttpRoute. Для управления маршрутом IHttpRoute предоставляет следующие свойства:
RouteTemplate
: шаблон URL, который применяется для сопоставления с запросом
Defaults
: возвращает объект IDictionary<string, object>
, содержащий в виде пар ключ-значения наборы параметров и их значения по умолчанию
Constraints
: содержит набор ограничений маршрута в виде объекта IDictionary<string, object>
DataTokens
: возвращает данные параметров и их значений маршрута в виде объекта IDictionary<string, object>
Handler
: возвращает обработчик маршрута - объект HttpMessageHandler
Объект HttpRequest.RouteData, хранящий извлеченные из запроса параметры маршрута, представляет реализацию интерфейса IHttpRouteData. Web Api также представляет встроенную реализацию этого интерфейса - класс HttpRouteData. Интерфейс IHttpRouteData определяет два свойства:
Route: объект IHttpRoute, представляющий текущий маршрут
Values: объект IDictionary<string, object>
, содержащий данные маршрута
Хотя каждый запрос сопоставляется только с одним маршрутом, но в приложении может быть определено несколько маршрутов. Все они попадают в коллекцию HttpRouteCollection. Для управления маршрутами в классе определены следующие методы и свойства:
CreateRoute(template, defaults, constraints)
: создает объект IHttpRoute, который принимает указанные шаблон URL, значения по
умолчанию и ограничения
CreateRoute(template, defaults, constraints, tokens)
: то же самое, плюс маршрут принимает токены значений маршрута
CreateRoute(template, defaults, constraints, tokens, handler)
: то же самое, плюс маршрут принимает обработчик маршрута
Add(name, route)
: добавляет новый маршрут
Clear()
: удаляет все маршруты
Contains(route)
: возвращает true, если коллекция содержит маршрут
Insert(index, name, route)
: добавляет маршрут route с именем name по определенную индексу в коллекцию
Remove(name)
: удаляет маршрут с определенным именем
this[int]
: получает маршрут из коллекции по определенному индексу
this[name]
: получает маршрут с определенным именем
IgnoreRoute(name, template)
: регистрирует маршрут с определенным именем и шаблоном, который не будет обрабатываться Web API
IgnoreRoute(name, template, constraints)
: регистрирует маршрут с определенным именем и шаблоном и ограничениями constraints, который не будет обрабатываться Web API
MapHttpRoute(name, template)
: создает и регистрирует маршрут с определенным именем и шаблоном
MapHttpRoute(name, template, defaults)
: создает и регистрирует маршрут с определенным именем, шаблоном и значениями по умолчанию
MapHttpRoute(name, template, defaults, constraints)
: создает и регистрирует маршрут с определенным именем, шаблоном, значениями по
умолчанию и ограничениями
MapHttpRoute(name, template, defaults, constraints, handler)
: создает и регистрирует маршрут с определенным именем, шаблоном, значениями по
умолчанию, ограничениями и обработчиком
Определение маршрутов по умолчанию производится в файле WebApiConfig.cs. Если мы откроем данный файл, то уже увидим регистрацию одного маршрута:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
Обратиться к коллекции маршрутов мы можем, используя свойство Routes
, определенное у класса конфигурации Web Api HttpConfiguration
Шаблон позволяет сопоставить запрос с определенным маршрутом. В Web API шаблоны определяются также, как и в MVC. В частности, здесь определен шаблон "api/{controller}/{id}", где параметр id является необязательным. Поэтому данный маршрут будет соответствовать, например, запросу api/values/5, где "values" будет сопоставляться с названием контроллера, а число 5 - с параметром id. Поскольку Web API использует тип запроса HTTP (POST/PUT/GET) для сопоставления с методом контроллера, то мы можем опустить в шаблоне сегмент для метода.
Обратите внимание на префикс api, с которого начинается шаблон. Хотя он применяется по умолчанию и часто используется в реальных приложениях Web Api, но его наличие необязательно. Смысл его использования состоит в том, чтобы разграничить маршруты Web API и MVC, так как по умолчанию в приложении ASP.NET MVC + Web API регистрируются как маршруты mvc, так и маршруты Web Api. Если они будут идентичными, то может возникнуть проблема сопоставления, особенно если маршрут MVC и маршрут Web Api используют один и тот же шаблон.
В то же время это не является обязательной формой определения маршрутов. Мы можем использовать шаблон, который включает в том числе и метод контроллера. Например, изменим класс в файле WebApiConfig.cs следующим образом:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "BookRoute", routeTemplate: "api/{controller}/{action}" ); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
И если у нас в контроллере определен, например, метод GetValue
:
public class ValuesController : ApiController { public string GetValue() { return "getvalue"; } }
то мы можем обратиться к этому методу с помощью запроса: api/values/getvalue
Если мы предоставим для определенного сегмента значения по умолчанию, то при сопоставлении маршрута с запросом может опускаться данный сегмент. Например,
routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = "5" } );
Даже если мы не используем при запросе сегмент для id: http://localhost/api/values, запрос все равно будет соответствовать маршруту, так использовано значение по умолчанию, то есть id будет в данном случае равно 5.
Если мы не хотим, чтобы метод сопоставлялся с определенным маршрутом, то мы можем пометить его атрибутом NonAction:
[NonAction] public string GetValue() { return "getvalue"; }
Теперь он не будет обрабатывать запросы, даже если он будет единственным подходящим для этого методом.