Содержание
Любой проект ASP.NET Core Web API на основе контроллеров состоит из одного или нескольких классов — контроллеров, выполняющих определенные действия. Контроллер — это тот компонент, который обеспечивает взаимосвязь между пользователем и приложением. Он обрабатывает входящие запросы и, либо, сразу генерирует данные для ответа, либо использует модель для манипуляции с данными и, затем, генерирует данные для ответа. В проектах ASP.NET Core Web API используются соглашения, в соответствии с которыми, обычные классы C# могут считаться контроллерами.
Что является контроллером в ASP.NET Core Web API?
С точки зрения ASP.NET Core, контроллер – это класс C#, соответствующий одному или нескольким соглашениям, который выполняет определенные действия, то есть, в терминах C# – содержит методы, которые обрабатывают запросы пользователей.
Действие контроллера — это метод, определенный в классе контроллера и содержащий специальный атрибут, указывающий какие запросы поддерживает действие. Например, в шаблонном приложении ASP.NET Core Web API создается контроллер:
[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] public IEnumerable<WeatherForecast> Get() { _logger.LogError("Сообщение из WeatherForecastController с уровнем Error"); 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(); } }
По соглашению, в проектах ASP.NET Core Web API контроллерами являются классы, обладающие одним или несколькими признаками:
- Класс содержит в названии суффикс
Controller
- Для класса определен атрибут
[ApiController]
- Класс унаследован от класса
ControllerBase
или, реже, отController
Например, посмотрим на объявление контроллера, представленного выше
[ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase
здесь присутствуют все три признака — суффикс Controller
, атрибут [ApiController]
, а сам класс — наследник ControllerBase
. У этого контроллера определено одно действие:
[HttpGet] public IEnumerable<WeatherForecast> Get() { //код действия }
Так как у метода Get()
определен специальный атрибут [HttpGet]
, то этот метод считается действие контроллера, которое обрабатывает входящие GET-запросы. Теперь рассмотрим какие возможности и приемущества дают те или иные признаки контроллера.
Атрибут [ApiController]
Атрибут [ApiController]
включает сразу несколько специализированных схем поведения API, а именно:
- Обязательная маршрутизация на основе атрибутов
- Автоматические отклики HTTP 400
- Вывод параметров источника привязки
- Сведения о проблемах для кодов состояния ошибки
Кратко разберемся с этими схемами, а далее — рассмотрим некоторые из них более подробно в следующих частях этого руководства.
Обязательная маршрутизация на основе атрибутов
В общем случае, маршрутизация в ASP.NET Core — это механизм сопоставления входящих HTTP-запросов с конкретными обработчиками (конечными точками, endpoints) в приложении. Применительно к ASP.NET Core Web API, маршрутизация — это механизм сопоставления входящего HTTP-запроса с действием контроллера.
В ASP.NET Core могут использоваться различные механизмы маршрутизации — у ASP.NET Core MVC может быть свой механизм маршрутизации, у Minimal API — свой, мы можем комбинировать эти механизмы, если это потребуется, однако, если мы определяем в нашем приложении контроллер с атрибутом [ApiController]
, то мы обязаны использовать механизм маршрутизации к действиям контроллера только с использованием атрибутов. Что это означает? Это означает, что для контроллера в целом или для отдельных его действий должны определяться специальные атрибуты, в которых мы должны указывать путь к действию. Например, вернемся к стандартному контроллеру:
[ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase
здесь мы видим атрибут
[Route("[controller]")]
в котором используется специальный маркер [controller]
, который указывает на то, что вместо этого маркера в URL должно подставляться имя контроллера без суффикса. Обратите внимание на то, как выглядит запрос в http-файле проекта:
GET {{WebApplication3_HostAddress}}/weatherforecast/ Accept: application/json
Атрибут Route
— это один из атрибутов маршрутизации. С другими атрибутами мы обязательно познакомимся более детально в следующих частях.
Автоматические отклики HTTP 400
Еще одна схема, которая включается при использовании атрибута [ApiController]
. Включение этой схемы означает, что в случае, если запрос пользователя будет составлен некорректно, то ASP.NET Core самостоятельно сгенерирует ответ (по умолчанию в формате JSON) с кодом HTTP 400 и описанием возникшей проблемы и этот ответ будет соответствовать спецификации RFC 7807. Об этом отклике мы также обязательно поговорим, когда будем разбираться с моделями в ASP.NET Core Web API.
Вывод параметров источника привязки
Большинство API не только отдает ответ пользователю, но и может принимать от него какие-либо данные, например, данные для создания учетных записей, параметры фильтрации и поиска данных и так далее. Все эти данные в ASP.NET Core могут передаваться различными способами — через параметры запроса, в теле запроса и так далее, которые называются источниками привязки. Использование атрибута [ApiController]
применяет специальные правила привязки к источникам, позволяя избежать лишней рутинной работы и, при необходимости, изменять приоритет тех или иных источников привязки, используя специальные атрибуты.
Сведения о проблемах для кодов состояния ошибки
Если в результате выполнения запроса к API происходит ошибка, то при использовании атрибута [ApiController]
, ASP.NET Core сгенерирует ответ, соответствующий спецификации RFC 7807. Этот пример можно продемонстрировать уже сейчас, не вдаваясь особо в подробности его реализации. Измените код действия Get()
в контроллере WeatherForecastController
шаблонного приложения ASP.NET Core следующим образом:
public ActionResult<IEnumerable<WeatherForecast>> Get() { return NotFound(); _logger.LogError("Сообщение из WeatherForecastController с уровнем Error"); 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(); }
Естественно, что код находящийся после return не будет выполняться, но нам это и не нужно. Здесь мы просто возвращаем пользователю на его запрос ответ с кодом 404 Not Found. Без использования атрибута [ApiController]
мы бы увидели следующий ответ сервера:
Если же мы применяем атрибут, то ответ сервера будет таким:
Как было сказано ранее, со всеми этими схемами поведения мы разберемся детально в следующих частях руководства. А пока, перейдем к следующему признаку контроллера.
Классы ControllerBase и Controller
Класс ControllerBase
предоставляет методы и свойства для обработки HTTP-запросов, например, такие методы, как NotFound()
для возврата пользователю кода состояния 404 или Ok()
и т.д. Например, мы можем определить следующий контроллер:
[Route("[controller]")] public class First: ControllerBase { [HttpGet] public OkResult SayOk() { return Ok(); //метод ControllerBase.Ok() } [HttpDelete] public BadRequestResult SayBadRequest() { return BadRequest();//метод ControllerBase.BadRequest() } }
Наиболее часто, именно этот класс является базовым для контроллеров в проектах Web API.
Что касается класса Controller
, то этот класс является наследником ControllerBase
и добавляет функциональность работы с представлениями. Поэтому, класс Controller
оправдано использовать только в том случае, если подразумевается, что ваш проект будет предоставлять и какой-либо визуальный интерфейс пользователям, например, с использованием MVC и, одновременно с этим, давать пользователям доступ к API вашего проекта.
Итого
Контроллером в проектах ASP.NET Core Web API считается класс, который содержит один или несколько признаков: содержит в названии суффикс Controller
, для класса определен атрибут [ApiController]
, наследуется от класса ControllerBase
или, реже, от Controller
. Атрибут [ApiController]
включает несколько специальных схем поведения, облегчающих нашу работу по созданию контроллеров API и обработке ошибок запросов.