Содержание
Любой проект 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 и обработке ошибок запросов.

