Как ASP.NET Core связывает данные HTTP-запроса с параметрами метода контроллера?

Ответ

Этот процесс называется привязкой модели (Model Binding). Платформа автоматически извлекает данные из различных частей запроса и преобразует их в аргументы метода действия.

Источники данных (в порядке приоритета по умолчанию):

  1. [FromBody]: Тело запроса (для JSON, XML). Используется системой форматирования ввода (Input Formatter), например, System.Text.Json.
  2. [FromForm]: Данные формы (application/x-www-form-urlencoded или multipart/form-data).
  3. [FromRoute]: Значения из шаблона маршрута (например, {id} в [HttpGet("api/products/{id}")]).
  4. [FromQuery]: Параметры строки запроса (после ? в URL).
  5. [FromHeader]: Значения HTTP-заголовков.

Процесс:

  1. Платформа ищет источник для каждого параметра, используя атрибуты или соглашения (например, сложные объекты по умолчанию берутся из тела).
  2. Сопоставляет имена свойств (регистронезависимо) с ключами в данных запроса.
  3. Преобразует строковые значения в целевые типы (int, DateTime, Guid и т.д.).

Пример с явным указанием источников:

[HttpGet("products/{id}/reviews")] // id берется из маршрута
public IActionResult GetReviews(
    int id, // Из маршрута
    [FromQuery] int page = 1, // Из query-строки: ?page=2
    [FromHeader(Name = "X-Sort-Order")] string sortOrder = "asc") // Из заголовка
{
    // ... логика действия
}

[HttpPost]
public IActionResult CreateProduct([FromBody] ProductDto product) // Из тела запроса (JSON)
{
    // ...
}

Валидация: После привязки автоматически выполняется валидация модели (если тип помечен атрибутами [Required], [Range] и т.д.). Невалидная модель приводит к ответу 400 Bad Request с деталями ошибок.

Ответ 18+ 🔞

Да ты посмотри, какая хуйня интересная происходит в ASP.NET Core! Это ж целый цирк с конями, называется привязка модели (Model Binding). Представь: твой запрос прилетает, а фреймворк как хитрая жопа, сам выковыривает оттуда данные и суёт их тебе в параметры метода. Магия, блядь!

Откуда он данные тянет, этот пройдоха? Да отовсюду, сука! И есть у него чёткий порядок, кто главнее:

  1. [FromBody]: Это прям святая святых — тело запроса. JSON там, XML. Тут работает специальный пацан, System.Text.Json, который эту кашу разбирает.
  2. [FromForm]: Старая добрая форма из браузера, где application/x-www-form-urlencoded или файлы в multipart/form-data.
  3. [FromRoute]: Выдернул прямо из URL, который сам же и сгенерировал! Типа api/products/{id} — и id уже твой.
  4. [FromQuery]: Всё, что наболтали после знака вопроса в адресной строке (?page=1&sort=name). Мелочёвка, но нужная.
  5. [FromHeader]: А это вообще из заголовков HTTP вытаскивает. Шпионская хуйня!

Как это работает-то, блядь?

  1. Фреймворк, как сыщик, ищет для каждого твоего параметра источник: смотрит на атрибуты или по умолчанию догадывается (сложный объект — значит, из тела).
  2. Находит имена свойств в данных запроса, ему похуй на регистр букв.
  3. И начинает преобразовывать эти строки во что надо: в int, DateTime, Guid — во всё, что попросишь. Если, конечно, сможет, а не упрётся в ерунду.

Смотри, как явно указать, откуда че тащить:

[HttpGet("products/{id}/reviews")] // id тут уже в маршруте зашит
public IActionResult GetReviews(
    int id, // Сам возьмёт из маршрута, ясень пень
    [FromQuery] int page = 1, // А это из query-строки: ?page=2
    [FromHeader(Name = "X-Sort-Order")] string sortOrder = "asc") // А это вообще из заголовка, чтоб его!
{
    // ... ну и дальше твоя логика, чё
}

[HttpPost]
public IActionResult CreateProduct([FromBody] ProductDto product) // А тут целый объект из JSON в теле запроса
{
    // ...
}

А вот самый сок, слушай сюда! После того как всё привязал, он валидацию запускает автоматом! Если ты свойства пометил [Required] или [Range] — он это проверит. И если данные хуёвые, он не будет мозги тебе парить, а сразу отправит клиенту 400 Bad Request со всеми подробностями, где и как он накосячил. Красота, ёпта!