Маршрутизация с использованием атрибута Route, которую мы рассмотрели в предыдущей части используется в проектах ASP.NET Core Web API наиболее часто, так как многократное применение этого атрибута к цели (классу или методу) позволяет создавать гибкую систему маршрутизации. Однако, при необходимости, мы можем настраивать маршрутизацию в контроллере также и с помощью атрибутов HTTP-команд.
Атрибуты HTTP-команд
Атрибуты HTTP-команд определяют какие команды HTTP будут обрабатываться тем или иным действие контроллера. На данный момент, в ASP.NET Core Web API определены следующие атрибуты HTTP-команд:
| Атрибут | Описание |
[HttpGet] |
Действие контроллера обрабатывает GET-запросы |
[HttpPost] |
Действие контроллера обрабатывает POST-запросы |
[HttpPut] |
Действие контроллера обрабатывает PUT-запросы |
[HttpDelete] |
Действие контроллера обрабатывает DELETE-запросы |
[HttpHead] |
Действие контроллера обрабатывает HEAD-запросы |
[HttpPatch] |
Действие контроллера обрабатывает PATCH-запросы |
[HttpOptions] |
Действие контроллера обрабатывает OPTIONS-запросы |
Все классы этих атрибутов имеют схожее описание, являются наследниками класса HttpMethodAttribute и содержат следующие свойства:
Http |
Список поддерживаемых методов HTTP. Например, для HttpGet — это будет только GET, для HttpPost — POST и т.д. |
Name |
Имя маршрута. |
Order |
Порядок маршрута. Сначала выполняются маршруты с более низким порядком. |
Template |
Шаблон маршрута. Может иметь значение null. |
В данном случае, для нас наиболее важным свойством является свойство Template с помощью которого мы можем задавать шаблон маршрута для действия контроллера. Рассмотрим несколько примеров использования атрибутов HTTP-команд для настройки системы маршрутизации в приложениях ASP.NET Core Web API.
Маршрутизация с использованием атрибутов HTTP-команд
Для рассмотрения примеров, воспользуемся шаблоном приложения ASP.NET Core Web API с использованием контроллеров. Изменим контроллер WeatherForecastController следующим образом:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet("/weather")] //шаблон маршрута
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
здесь мы указали у действия контроллера Get() атрибут HttpGet в параметрах которого определили шаблон маршрута /weather. Также, у класса контроллера определен уже известный нам атрибут Route. Теперь метод API будет нам доступен по пути /weather. Всё в соответствии с тем, как ASP.NET Core выводит параметры маршрутов.
Также, как и при использовании атрибута Route, мы можем использовать зарезервированные имена в шаблонах маршрутов, а также применять атрибуты http-команд многократно к одному и тому же действию контроллера, например,
[HttpGet("[action]")] //шаблон будет объединен с шаблоном маршрута для контроллера
[HttpGet("/")] //шаблон НЕ будет объединен с шаблоном маршрута для контроллера
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
В первом атрибуте мы использовали зарезервированное имя action вместо которого в маршрут подставляется имя действия контроллера. Также, следует отметить ещё один момент, касающийся настройки системы маршрутизации с использованием атрибутов:
Изменим наш пример следующим образом:
[ApiController]
[Route("[controller]")] //первый шаблон маршрута
[Route("api/[controller]")] //второй шаблон маршрута
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet("[action]")] //первый шаблон действия
[HttpGet("weather")] //второй шаблон действия
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
В итоге, мы получим четыре маршрута:
- /WeatherForecast/Get
- /api/WeatherForecast/Get
- /WeatherForecast/weather
- /api/WeatherForecast/weather
Здесь каждый шаблон маршрута контроллера был объединен с каждым шаблоном маршрута для действия. Аналогичные правила буду действовать также и при использовании только атрибутов Route.
Итого
Помимо атрибута Route, мы также можем организовать систему маршрутизации к действиям контроллеров в приложениях ASP.NET Core Web API и с помощью атрибутов http-команд. Каждый атрибут http-команды может использовать свойство Template для указания шаблона маршрута. Действие этого свойства полностью аналогично одноименному свойству атрибута Route, а именно: шаблоны маршрутов действий не объединяются с шаблонами маршрутов контроллера, если шаблон маршрута действия начинается с символа / или ~/. Объединение маршрутов контроллера и действий осуществляется по принципу «многие-ко-многим», то есть каждый шаблон маршрута контроллера будет объединяться с каждым шаблоном маршрута действия.