Создание веб-API с помощью ASP.NET Core

Авторы: Скотт Адди (Scott Addie) и Том Дайкстра (Tom Dykstra)

ASP.NET Core поддерживает создание служб RESTful, также известных как веб-API, с помощью C#. Для обработки запросов веб-API использует контроллеры. Контроллеры в веб-API — это классы, производные от . В этой статье показано, как использовать контроллеры для обработки веб-запросов API.

Просмотреть или скачать образец кода. (Инструкция по скачиванию.)

Класс ControllerBase

Веб-API состоит из одного или нескольких классов контроллера, которые являются производными от ControllerBase. Шаблон проекта веб-API предоставляет начальный контроллер:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Не создавайте контроллер веб-API путем наследования от класса Controller. Controller является производным от ControllerBase и добавляет поддержку для представлений, обеспечивая обработку веб-страниц, а не запросов веб-API. Существует одно исключение из этого правила: если вы планируете использовать один и тот же контроллер для представлений и веб-API, сделайте его производным от Controller.

Класс ControllerBase предоставляет множество свойств и методов, которые удобны для обработки HTTP-запросов. Например, ControllerBase.CreatedAtAction возвращает код состояния 201.

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Вот еще примеры методов, предоставляющих ControllerBase.

Метод Примечания
BadRequest Возвращает код состояния 400.
NotFound Возвращает код состояния 404.
PhysicalFile Возвращает файл.
TryUpdateModelAsync Вызывает привязку модели.
TryValidateModel Вызывает проверку модели.

Список всех доступных методов и свойств см. здесь: ControllerBase.

Атрибуты

Пространство имен Microsoft.AspNetCore.Mvc предоставляет атрибуты, которые можно использовать для настройки поведения контроллеров и методов действия веб-API. В следующем примере атрибуты используются для указания поддерживаемой команды действия HTTP и всех известных кодов состояния HTTP, которые могут быть возвращены:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Вот еще примеры доступных атрибутов.

Атрибут Примечания
[Route] Определяет шаблон URL-адреса для контроллера или действия.
[Bind] Задает префикс и свойства, которые добавляются для привязки модели.
[HttpGet] Определяет действие, которое поддерживает команду действия HTTP GET.
[Consumes] Указывает типы данных, которые принимает действие.
[Produces] Указывает типы данных, которые возвращает действие.

Список доступных атрибутов см. в пространстве имен Microsoft.AspNetCore.Mvc.

Атрибут ApiController

Атрибут [ApiController] можно применить к классу контроллера для включения следующих специализированных схем поведения API:

Для использования функции Сведения о проблеме для кодов состояния ошибки требуется совместимая версия 2.2 и выше. Для реализации других функций требуется совместимая версия 2.1 и выше.

Для реализации этих функций необходима версия совместимости, начиная с 2.1.

Атрибут в определенных контроллерах

Атрибут [ApiController] может применяться к определенным контроллерам, как показано в следующем примере из шаблона проекта:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Атрибут в нескольких контроллерах

Один из подходов к использованию атрибута на более чем одном контроллере заключается в создании пользовательского базового класса контроллера, аннотированного атрибутом [ApiController]. В следующем примере демонстрируется пользовательский базовый класс и производный от него контроллер:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase

Атрибут в сборке

Если для параметра Версия совместимости задано значение 2,2 или более поздней версии, атрибут может быть применен к сборке. Аннотирование этим способом применяет поведение веб-API ко всем контроллерам в сборке. Его нельзя отменить для отдельных контроллеров. Примените атрибут уровня сборки к объявлению пространства имен, окружающему класс Startup:

[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

Обязательная маршрутизация атрибутов

Атрибут [ApiController] требует обязательной маршрутизации атрибутов. Пример:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase

Действия недоступны через стандартные маршруты , определенные, UseMvc или UseMvcWithDefaultRoute в Startup.Configure .

Автоматические отклики HTTP 400

Благодаря атрибуту [ApiController] ошибки проверки модели автоматически активируют отклик HTTP 400. В результате следующий код ненужен в методе действия:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

Для выполнения предыдущей проверки ASP.NET Core MVC использует фильтр действий ModelStateInvalidFilter.

Отклик BadRequest по умолчанию

Если задана версия совместимости 2.1, для ответов HTTP 400 по умолчанию возвращается тип отклика SerializableError. Следующий текст запроса является примером сериализованного типа:

{
  "": [
    "A non-empty request body is required."
  ]
}

Если задана версия совместимости 2.2 или более поздние версии, для ответов HTTP 400 по умолчанию возвращается тип отклика ValidationProblemDetails. Следующий текст запроса является примером сериализованного типа:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

Тип ValidationProblemDetails:

  • предоставляет распознаваемый компьютером формат для указания ошибок в откликах веб-API;
  • соответствует спецификации RFC 7807.

Чтобы обеспечить согласованность автоматических и настраиваемых ответов, вызовите метод ValidationProblem, а не BadRequest. ValidationProblem возвращает объект ValidationProblemDetails, а также автоматический ответ.

Запись в журнал автоматических откликов HTTP 400

Чтобы вести журнал автоматических ответов 400, установите InvalidModelStateResponseFactory свойство делегата для выполнения пользовательской обработки в Startup.ConfigureServices . По умолчанию InvalidModelStateResponseFactory использует ProblemDetailsFactory для создания экземпляра ValidationProblemDetails .

В следующем примере показано, как получить экземпляр ILogger<TCategoryName> для записи в журнал сведений об автоматическом ответе 400:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        // To preserve the default behavior, capture the original delegate to call later.
        var builtInFactory = options.InvalidModelStateResponseFactory;

        options.InvalidModelStateResponseFactory = context =>
        {
            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Startup>>();

            // Perform logging here.
            // ...

            // Invoke the default behavior, which produces a ValidationProblemDetails response.
            // To produce a custom response, return a different implementation of IActionResult instead.
            return builtInFactory(context);
        };
    });

Отключение автоматической активации отклика HTTP 400

Чтобы отключить автоматическую активацию отклика HTTP 400, задайте свойству SuppressModelStateInvalidFilter значение true. Добавьте выделенный ниже код в Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

Вывод параметров источника привязки

Атрибут источника привязки определяет расположение, в котором находится значение параметра действия. Существуют следующие атрибуты источника привязки.

Атрибут Источник привязки
[FromBody] Текст запроса
[FromForm] Данные формы в тексте запроса
[FromHeader] Заголовок запроса
[FromQuery] Параметры строки запроса для запроса
[FromRoute] Данные маршрута из текущего запроса
[FromServices] Служба запросов, внедренная в качестве параметра действия

Предупреждение

Не используйте [FromRoute], если значения могут содержать %2f (то есть /). Для %2f не будет применяться отмена экранирования /. Используйте [FromQuery], если значение может содержать %2f.

Без атрибута [ApiController] или атрибутов источника привязки, таких как [FromQuery], среда выполнения ASP.NET Core попытается использовать связыватель модели для составного объекта. Связыватель модели для составного объекта извлекает данные из поставщиков значений в определенном порядке.

В следующем примере атрибут [FromQuery] указывает, что значение параметра discontinuedOnly задано в строке запроса URL-адреса для запроса:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

Атрибут [ApiController] применяет правила зависимости к источникам данных по умолчанию для параметров действий. Эти правила избавляют от необходимости вручную определять источники привязки путем применения атрибутов к параметрам действий. Правила зависимости источника привязки работают следующим образом:

  • [FromBody] выводится для параметров сложного типа. Исключением из правила зависимости [FromBody] является любой сложный встроенный тип со специальным значением, такой как IFormCollection и CancellationToken. Код определения источника привязки игнорирует эти особые типы.
  • [FromForm] выводится для параметров действия с типом IFormFile и IFormFileCollection. Он не выводится ни для каких простых или определяемых пользователем типов.
  • [FromRoute] выводится для любого имени параметра действия, соответствующего параметру в шаблоне маршрута. Если параметру действия соответствуют несколько маршрутов, любое значение маршрута рассматривается как [FromRoute].
  • [FromQuery] выводится для любых других параметров действия.

Заметки о выводе FromBody

[FromBody] не определен для простых типов, таких как string или int. Таким образом, атрибут [FromBody] должен использоваться для простых типов, когда требуются эти функции.

Если у действия более одного параметра для привязки из текста запроса, выдается исключение. Например, все следующие сигнатуры метода действия вызывают исключение:

  • [FromBody] выводится для обеих параметров, так как они являются сложными типами.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Атрибут [FromBody], заданный одному параметру, выводится для другого, так как это сложный тип.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Атрибут [FromBody] выводится для обоих параметров.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Отключение правил зависимости

Чтобы отключить вывод источника привязки, задайте SuppressInferBindingSourcesForParameters значение true. Добавьте следующий код в Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

Вывод многокомпонентных запросов и запросов данных форм

Атрибут [ApiController] позволяет применить правило зависимости, когда параметр действия аннотирован атрибутом [FromForm]. При этом выводится тип содержимого запроса multipart/form-data.

Чтобы отключить поведение по умолчанию, задайте свойству SuppressConsumesConstraintForFormFileParameters значение true в Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

Сведения о проблемах для кодов состояния ошибки

Если задана версия совместимости, начиная с 2.2, MVC преобразовывает код ошибки (код состояния 400 и далее) в результат с ProblemDetails. ProblemDetailsТип основан на ProblemDetails для предоставления сведений об ошибках, доступных для чтения компьютера, в HTTP-ответе.

Рассмотрим следующий код в действии контроллера:

if (pet == null)
{
    return NotFound();
}

Метод NotFound создает код состояния HTTP 404 с текстом ProblemDetails. Пример:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001"
}

Отключение ответа ProblemDetails

Отключить автоматическое создание ProblemDetails для кодов состояния ошибок можно, задав свойству SuppressMapClientErrors значение true. Добавьте следующий код в Startup.ConfigureServices:

services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
            "https://httpstatuses.com/404";
    });

Определение поддерживаемых типов содержимого запросов с помощью атрибута [Consumes]

По умолчанию действие поддерживает все доступные типы содержимого запросов. Например, если приложение настроено для поддержки как JSON, так и модулей форматирования вводаXML, действие поддерживает несколько типов содержимого, включая и application/xml .

Атрибут [Consumes] позволяет выполнять действие для ограничения поддерживаемых типов содержимого запросов. Примените атрибут [Consumes] к действию или контроллеру, указав один или несколько типов содержимого:

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

В приведенном выше коде действие CreateProduct указывает тип содержимого application/xml. Запросы, направляемые в это действие, должны определять заголовок Content-Typeapplication/xml. Запросы, не указывающие Content-Type заголовок application/xml результата, в ответ на Content-Type .

Атрибут [Consumes] также позволяет действию влиять на выбор с учетом типа содержимого входящего запроса, применяя ограничение типа. Рассмотрим следующий пример.

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

В приведенном выше коде для ConsumesController включена поддержка обработки запросов, отправляемых на URL-адрес https://localhost:5001/api/Consumes. Оба действия контроллера (PostJson и PostForm) обрабатывают запросы POST с одним и тем же URL-адресом. Если в атрибуте [Consumes] не применяется ограничение типа, возникает исключение неоднозначного соответствия.

Атрибут [Consumes] применяется к обоим действиям. Действие PostJson обрабатывает запросы, отправленные с заголовком Content-Typeapplication/json. Действие PostForm обрабатывает запросы, отправленные с заголовком Content-Typeapplication/x-www-form-urlencoded.

Дополнительные ресурсы

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Не создавайте контроллер веб-API путем наследования от класса Controller. Controller является производным от ControllerBase и добавляет поддержку для представлений, обеспечивая обработку веб-страниц, а не запросов веб-API. Существует одно исключение из этого правила: если вы планируете использовать один и тот же контроллер для представлений и веб-API, сделайте его производным от Controller.

Класс ControllerBase предоставляет множество свойств и методов, которые удобны для обработки HTTP-запросов. Например, ControllerBase.CreatedAtAction возвращает код состояния 201.

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Вот еще примеры методов, предоставляющих ControllerBase.

Метод Примечания
BadRequest Возвращает код состояния 400.
NotFound Возвращает код состояния 404.
PhysicalFile Возвращает файл.
TryUpdateModelAsync Вызывает привязку модели.
TryValidateModel Вызывает проверку модели.

Список всех доступных методов и свойств см. здесь: ControllerBase.

Атрибуты

Пространство имен Microsoft.AspNetCore.Mvc предоставляет атрибуты, которые можно использовать для настройки поведения контроллеров и методов действия веб-API. В следующем примере атрибуты используются для указания поддерживаемой команды действия HTTP и всех известных кодов состояния HTTP, которые могут быть возвращены:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? 
             _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

    return CreatedAtAction(nameof(GetById), new { id = pet.Id }, pet);
}

Вот еще примеры доступных атрибутов.

Атрибут Примечания
[Route] Определяет шаблон URL-адреса для контроллера или действия.
[Bind] Задает префикс и свойства, которые добавляются для привязки модели.
[HttpGet] Определяет действие, которое поддерживает команду действия HTTP GET.
[Consumes] Указывает типы данных, которые принимает действие.
[Produces] Указывает типы данных, которые возвращает действие.

Список доступных атрибутов см. в пространстве имен Microsoft.AspNetCore.Mvc.

Атрибут ApiController

Атрибут [ApiController] можно применить к классу контроллера для включения следующих специализированных схем поведения API:

Для использования функции Сведения о проблеме для кодов состояния ошибки требуется совместимая версия 2.2 и выше. Для реализации других функций требуется совместимая версия 2.1 и выше.

Для реализации этих функций необходима версия совместимости, начиная с 2.1.

Атрибут в определенных контроллерах

Атрибут [ApiController] может применяться к определенным контроллерам, как показано в следующем примере из шаблона проекта:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Атрибут в нескольких контроллерах

Один из подходов к использованию атрибута на более чем одном контроллере заключается в создании пользовательского базового класса контроллера, аннотированного атрибутом [ApiController]. В следующем примере демонстрируется пользовательский базовый класс и производный от него контроллер:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("api/[controller]")]
public class PetsController : MyControllerBase

Атрибут в сборке

Если для параметра Версия совместимости задано значение 2,2 или более поздней версии, атрибут может быть применен к сборке. Аннотирование этим способом применяет поведение веб-API ко всем контроллерам в сборке. Его нельзя отменить для отдельных контроллеров. Примените атрибут уровня сборки к объявлению пространства имен, окружающему класс Startup:

[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

Обязательная маршрутизация атрибутов

Атрибут [ApiController] требует обязательной маршрутизации атрибутов. Пример:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Действия недоступны через стандартные маршруты , определенные UseMvcWithDefaultRoute в или в Startup.Configure .

Автоматические отклики HTTP 400

Благодаря атрибуту [ApiController] ошибки проверки модели автоматически активируют отклик HTTP 400. В результате следующий код ненужен в методе действия:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

Для выполнения предыдущей проверки ASP.NET Core MVC использует фильтр действий ModelStateInvalidFilter.

Отклик BadRequest по умолчанию

Если задана версия совместимости 2.1, для ответов HTTP 400 по умолчанию возвращается тип отклика SerializableError. Следующий текст запроса является примером сериализованного типа:

{
  "": [
    "A non-empty request body is required."
  ]
}

Если задана версия совместимости 2.2 или более поздние версии, для ответов HTTP 400 по умолчанию возвращается тип отклика ValidationProblemDetails. Следующий текст запроса является примером сериализованного типа:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|7fb5e16a-4c8f23bbfc974667.",
  "errors": {
    "": [
      "A non-empty request body is required."
    ]
  }
}

Тип ValidationProblemDetails:

  • предоставляет распознаваемый компьютером формат для указания ошибок в откликах веб-API;
  • соответствует спецификации RFC 7807.

Чтобы обеспечить согласованность автоматических и настраиваемых ответов, вызовите метод ValidationProblem, а не BadRequest. ValidationProblem возвращает объект ValidationProblemDetails, а также автоматический ответ.

Запись в журнал автоматических откликов HTTP 400

См. описание проблемы записи в журнал автоматических ответов HTTP 400 для ошибок проверки модели (aspnet/AspNetCore.Docs#12157).

Отключение автоматической активации отклика HTTP 400

Чтобы отключить автоматическую активацию отклика HTTP 400, задайте свойству SuppressModelStateInvalidFilter значение true. Добавьте выделенный ниже код в Startup.ConfigureServices:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Вывод параметров источника привязки

Атрибут источника привязки определяет расположение, в котором находится значение параметра действия. Существуют следующие атрибуты источника привязки.

Атрибут Источник привязки
[FromBody] Текст запроса
[FromForm] Данные формы в тексте запроса
[FromHeader] Заголовок запроса
[FromQuery] Параметры строки запроса для запроса
[FromRoute] Данные маршрута из текущего запроса
[FromServices] Служба запросов, внедренная в качестве параметра действия

Предупреждение

Не используйте [FromRoute], если значения могут содержать %2f (то есть /). Для %2f не будет применяться отмена экранирования /. Используйте [FromQuery], если значение может содержать %2f.

Без атрибута [ApiController] или атрибутов источника привязки, таких как [FromQuery], среда выполнения ASP.NET Core попытается использовать связыватель модели для составного объекта. Связыватель модели для составного объекта извлекает данные из поставщиков значений в определенном порядке.

В следующем примере атрибут [FromQuery] указывает, что значение параметра discontinuedOnly задано в строке запроса URL-адреса для запроса:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

Атрибут [ApiController] применяет правила зависимости к источникам данных по умолчанию для параметров действий. Эти правила избавляют от необходимости вручную определять источники привязки путем применения атрибутов к параметрам действий. Правила зависимости источника привязки работают следующим образом:

  • [FromBody] выводится для параметров сложного типа. Исключением из правила зависимости [FromBody] является любой сложный встроенный тип со специальным значением, такой как IFormCollection и CancellationToken. Код определения источника привязки игнорирует эти особые типы.
  • [FromForm] выводится для параметров действия с типом IFormFile и IFormFileCollection. Он не выводится ни для каких простых или определяемых пользователем типов.
  • [FromRoute] выводится для любого имени параметра действия, соответствующего параметру в шаблоне маршрута. Если параметру действия соответствуют несколько маршрутов, любое значение маршрута рассматривается как [FromRoute].
  • [FromQuery] выводится для любых других параметров действия.

Заметки о выводе FromBody

[FromBody] не определен для простых типов, таких как string или int. Таким образом, атрибут [FromBody] должен использоваться для простых типов, когда требуются эти функции.

Если у действия более одного параметра для привязки из текста запроса, выдается исключение. Например, все следующие сигнатуры метода действия вызывают исключение:

  • [FromBody] выводится для обеих параметров, так как они являются сложными типами.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • Атрибут [FromBody], заданный одному параметру, выводится для другого, так как это сложный тип.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Атрибут [FromBody] выводится для обоих параметров.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Примечание

В ASP.NET Core 2.1 параметры типа коллекции, такие как списки и массивы, ошибочно выводятся как [FromQuery]. Для этих параметров следует использовать атрибут [FromBody], если они должны быть привязаны из текста запроса. Это поведение, при котором параметры типа коллекции выводятся для привязки из текста по умолчанию, исправлено в версии ASP.NET Core, начиная с 2.2.

Отключение правил зависимости

Чтобы отключить вывод источника привязки, задайте SuppressInferBindingSourcesForParameters значение true. Добавьте следующий код в Startup.ConfigureServices:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Вывод многокомпонентных запросов и запросов данных форм

Атрибут [ApiController] позволяет применить правило зависимости, когда параметр действия аннотирован атрибутом [FromForm]. При этом выводится тип содержимого запроса multipart/form-data.

Чтобы отключить поведение по умолчанию, задайте свойству SuppressConsumesConstraintForFormFileParameters значение true в Startup.ConfigureServices:

services.Configure<ApiBehaviorOptions>(options =>
{
    options.SuppressConsumesConstraintForFormFileParameters = true;
    options.SuppressInferBindingSourcesForParameters = true;
    options.SuppressModelStateInvalidFilter = true;
});

Сведения о проблемах для кодов состояния ошибки

Если задана версия совместимости, начиная с 2.2, MVC преобразовывает код ошибки (код состояния 400 и далее) в результат с ProblemDetails. ProblemDetailsТип основан на ProblemDetails для предоставления сведений об ошибках, доступных для чтения компьютера, в HTTP-ответе.

Рассмотрим следующий код в действии контроллера:

if (pet == null)
{
    return NotFound();
}

Метод NotFound создает код состояния HTTP 404 с текстом ProblemDetails. Пример:

{
  type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
  title: "Not Found",
  status: 404,
  traceId: "0HLHLV31KRN83:00000001"
}

Отключение ответа ProblemDetails

Отключить автоматическое создание ProblemDetails для кодов состояния ошибок можно, задав свойству SuppressMapClientErrors значение true. Добавьте следующий код в Startup.ConfigureServices:

Определение поддерживаемых типов содержимого запросов с помощью атрибута [Consumes]

По умолчанию действие поддерживает все доступные типы содержимого запросов. Например, если приложение настроено для поддержки как JSON, так и модулей форматирования вводаXML, действие поддерживает несколько типов содержимого, включая и application/xml .

Атрибут [Consumes] позволяет выполнять действие для ограничения поддерживаемых типов содержимого запросов. Примените атрибут [Consumes] к действию или контроллеру, указав один или несколько типов содержимого:

[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)

В приведенном выше коде действие CreateProduct указывает тип содержимого application/xml. Запросы, направляемые в это действие, должны определять заголовок Content-Typeapplication/xml. Запросы, не указывающие Content-Type заголовок application/xml результата, в ответ на Content-Type .

Атрибут [Consumes] также позволяет действию влиять на выбор с учетом типа содержимого входящего запроса, применяя ограничение типа. Рассмотрим следующий пример.

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

В приведенном выше коде для ConsumesController включена поддержка обработки запросов, отправляемых на URL-адрес https://localhost:5001/api/Consumes. Оба действия контроллера (PostJson и PostForm) обрабатывают запросы POST с одним и тем же URL-адресом. Если в атрибуте [Consumes] не применяется ограничение типа, возникает исключение неоднозначного соответствия.

Атрибут [Consumes] применяется к обоим действиям. Действие PostJson обрабатывает запросы, отправленные с заголовком Content-Typeapplication/json. Действие PostForm обрабатывает запросы, отправленные с заголовком Content-Typeapplication/x-www-form-urlencoded.

Дополнительные ресурсы