Генерация ответа от модели¶
Рассмотрим сценраий: создаем метод действия веб-API для возврата списка автомобилей:
[ApiController]
public class CarsController : Controller
{
[HttpGet("api/cars")]
public IEnumerable<string> ListCars()
{
return new string[] { "Nissan Micra", "Ford Focus" };
}
}
Как мы обсуждали, можно возвращать данные непосредственно из метода действия, и промежуточное ПО отформатирует их и передаст клиенту. Как оно узнает, какой формат использовать?
Процесс определения формата данных известен как согласование содержимого (content negotiation — conneg). В общих чертах это работает так: клиент отправляет типы контента, которые он может понять, в заголовке
Accept, а сервер выбирает один из них, форматирует ответ и отправляет в ответе заголовок content-type с указанием выбранного типа.Когда возвращается модель API, независимо от того, делается это напрямую или через
OkResult (или любой другой StatusCodeResult), и если ASP.NET Core не может вернуть результат в формате, указанном в Accept, будет использован формат JSON по умолчанию.Данные всегда сериализуются при помощи одной из реализаций
IOutputFormatter.
Настройка форматтеров по умолчанию — добавляем поддержку XML¶
По умолчанию настроены только форматтеры text/plain, text/html и application/json. Чтобы добавить вывод XML, нужно добавить форматтер вывода1. Для этого нужно настроить объект IMvcBuilder, возвращаемый из метода AddControllers:
Теперь передача заголовка
Accept: "text/xml" будет приводить к сериализации в XML.
Выбор формата с помощью согласования содержимого¶
Согласование содержимого (content negotiation) — это когда клиент сообщает, какие типы данных он может принимать, используя заголовок Accept, а сервер выбирает наиболее подходящий из них, который он может обработать. В целом, это так и работает, но в реализаци ASP.NET Core есть несколько особых случаев, которые нужно учитывать:
- по умолчанию возвращаются только MIME-типы
application/json,text/plainиtext/html. Можно добавить другие форматтерыIOutputFormatter; - по умолчанию, если в качестве модели API возвращается
null, как напрямую, так и черезStatusCodeResult, промежуточное ПО вернет ответ204 No Content; - если в качестве модели API возвращается строка, и не задан заголовок
Accept, ответ отформатируется какtext/plain; - если используется любой другой класс и либо отсутствует заголовок
Accept, либо запрашиваются только неподдерживаемые форматы, будет использоваться первый форматтер, который может сгенерировать ответ (обычно JSON); - если промежуточное ПО обнаружит, что запрос, вероятно, исходит от браузера (
Acceptсодержит*/*), то согласование содержимого не будет использоваться, ответ будет отформатирован как если быAcceptне был передан.
Эти правила можно настроить, например, в примере показано, как заставить промежуточное ПО учитывать браузерный Accept и удалить форматтер text/plain для строк:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
});
}
Дополнительные сведения, в том числе и об обходе обычных механизмов согласования содержимого можно найти в документации Microsoft
-
Технически таким образом добавляется и форматтер ввода XML, что означает, что теперь приложение может получать XML в запросах. Подробно о форматтерах, включая создание собственного, см. в документации ↩
Дата создания : 28 сентября 2022 г.