Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
ASP.NET Core MVC поддерживает форматирование данных ответа, используя указанные форматы или в ответ на запрос клиента.
Результаты действий для конкретного формата
Некоторые типы результатов действий характерны для определенного формата, например JsonResult и ContentResult. Действия могут возвращать результаты, которые всегда используют указанный формат, игнорируя запрос клиента для другого формата. Например, возвращение JsonResult возвращает данные в формате JSON, а возвращение ContentResult возвращает строковые данные в формате обычного текста.
Действие не обязано возвращать данные конкретного типа. ASP.NET Core поддерживает любое возвращаемое значение объекта. Результаты действий, возвращающих объекты, которые не относятся к типу IActionResult, сериализуются с помощью соответствующей реализации IOutputFormatter. Дополнительные сведения см. в разделе "Типы возвращаемых действий контроллера" в веб-API ASP.NET Core.
По умолчанию встроенный вспомогательный метод ControllerBase.Ok возвращает данные в формате JSON:
[HttpGet]
public IActionResult Get() =>
Ok(_todoItemStore.GetList());
Пример кода возвращает список элементов todo. С помощью средств разработчика браузера F12 или http-repl с предыдущим кодом отображается следующее:
- Заголовок ответа, содержащий тип контента:
application/json; charset=utf-8 - Заголовки запроса. Например, заголовок
Accept. Приведенный выше код игнорирует заголовокAccept.
Чтобы возвратить данные в формате обычного текста, используйте ContentResult и вспомогательный метод Content:
[HttpGet("Version")]
public ContentResult GetVersion() =>
Content("v1.0.0");
В приведенном выше коде возвращаемым Content-Type является text/plain.
Для действий с несколькими возвращаемыми типами возвращается значение IActionResult. Например, при возврате различных кодов состояния HTTP в зависимости от результата операции.
Согласование содержимого
Согласование содержимого происходит, когда клиент задает заголовок Accept. Для ASP.NET Core по умолчанию используется формат JSON. Согласование содержимого:
- реализуется с помощью ObjectResult;
- встроено в результаты действия с определенным кодом состояния, возвращаемые из вспомогательных методов; вспомогательные методы результатов действия основаны на
ObjectResult;
при возврате типа модели возвращаемым типом является ObjectResult.
Следующий метод действия использует вспомогательные методы Ok и NotFound:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
По умолчанию ASP.NET Core поддерживает следующие типы носителей:
application/jsontext/jsontext/plain
Такие средства, как Fiddler или curl, могут задать Accept заголовок запроса, чтобы указать формат возврата. Если заголовок Accept содержит тип, который поддерживается сервером, возвращается этот тип. Сведения о добавлении дополнительных форматировщиков приведены в следующем разделе.
Действия контроллера могут возвращать POCO (простые, старые объекты CLR). При возвращении POCO среда выполнения автоматически создает ObjectResult, которая оборачивает объект. Клиент получает отформатированный сериализованный объект. Если возвращаемый объект имеет значение null, возвращается ответ 204 No Content.
В следующем примере возвращается тип объекта:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
В приведенном выше коде запрос допустимого элемента todo возвращает 200 OK ответ. Запрос невалидного элемента todo возвращает ответ типа 204 No Content.
Заголовок Accept
Согласование содержимого выполняется только при наличии в запросе заголовка Accept. Если запрос содержит заголовок Accept, ASP.NET Core:
- перечисляет типы мультимедиа в заголовке Accept в порядке предпочтения;
- пытается найти форматировщик, который может создать ответ в одном из указанных форматов.
Если форматировщик, который может удовлетворить запрос клиента, не найден, ASP.NET Core:
- Возвращает значение
406 Not Acceptable, если MvcOptions.ReturnHttpNotAcceptable задано значениеtrue, или - - пытается найти первый форматировщик, который может создать ответ.
Если форматировщик, обеспечивающий требуемый формат, не настроен, используется первый форматировщик, способный отформатировать данный объект. Если в запросе не отображается заголовок Accept:
- Для сериализации ответа используется первый форматировщик, который может работать с объектом.
- Переговоры не ведутся. Сервер определяет возвращаемый формат.
Если заголовок Accept содержит */*, он игнорируется, если только RespectBrowserAcceptHeader не имеет значение true в MvcOptions.
Браузеры и согласование содержимого
В отличие от обычных клиентов API, веб-браузеры предоставляют заголовки Accept. Веб-браузеры указывают множество форматов, включая подстановочные знаки. Если платформа обнаруживает, что запрос поступает из браузера, по умолчанию выполняется следующее:
- Заголовок
Acceptигнорируется. - Содержимое возвращается с помощью первого зарегистрированного средства форматирования выходных данных, который может обрабатывать тип ответа, если иное не настроено.
Этот подход обеспечивает более согласованный интерфейс в браузерах при использовании API.
Чтобы настроить приложение для принятия заголовков браузера, задайте значение свойства true на RespectBrowserAcceptHeader.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Настройка форматировщиков
Приложения, которые должны поддерживать дополнительные форматы, могут добавлять соответствующие пакеты NuGet и настраивать поддержку. Существуют отдельные модули форматирования для ввода и вывода. Привязка модели использует форматировщики ввода. Форматировщики вывода используются для форматирования ответов. Сведения о создании пользовательского форматировщика см. в статье Пользовательские модули форматирования для веб-API в ASP.NET Core.
Добавление поддержки формата XML
Чтобы настроить XML-форматировщики, реализованные с помощью XmlSerializer, вызовите AddXmlSerializerFormatters.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
При использовании приведенного выше кода методы контроллера возвращают соответствующий формат на основе заголовка Accept запроса.
Настройте форматировщики с использованием System.Text.Json
Чтобы настроить функции для форматировщиков, основанных на System.Text.Json, используйте Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. Приведённый ниже код настраивает форматирование в PascalCase вместо форматирования в стиле camelCase по умолчанию.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
Следующий метод действия вызывает ControllerBase.Problem для создания ответа ProblemDetails.
[HttpGet("Error")]
public IActionResult GetError() =>
Problem("Something went wrong.");
ProblemDetails Ответ всегда в формате camelCase, даже если приложение задает формат PascalCase.
ProblemDetails соответствует RFC 7807, который определяет использование строчных букв.
Чтобы настроить параметры сериализации выходных данных для определенных действий, используйте JsonResult. Рассмотрим пример.
[HttpGet]
public IActionResult Get() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions
{
PropertyNamingPolicy = null
});
Добавьте поддержку формата JSON на основе Newtonsoft.Json.
Используются System.Text.Jsonформатировщики JSON по умолчанию. Чтобы использовать средства форматирования на основе Newtonsoft.Json, установите пакет NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson и настройте его в Program.cs.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
В приведенном вышеупомянутом коде вызов AddNewtonsoftJson настраивает следующие функции Web API, MVC и Razor Pages для использования Newtonsoft.Json:
- Методы форматирования входных и выходных данных, которые считывают и записывают JSON
- JsonResult
- Исправление JSON
- IJsonHelper
- TempData
Возможно, некоторые функции не будут оптимально работать с форматировщиками на основе System.Text.Json и будут требовать ссылки на форматировщики на основе Newtonsoft.Json. Продолжайте использовать форматтеры на основе Newtonsoft.Json, когда приложение:
- Использует атрибут
Newtonsoft.Json. Например,[JsonProperty]или[JsonIgnore]. - Настраивает параметры сериализации.
- Зависит от функций, предоставляемых
Newtonsoft.Json.
Чтобы настроить функции для форматировщиков на основе Newtonsoft.Json, используйте SerializerSettings.
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Чтобы настроить параметры сериализации выходных данных для определенных действий, используйте JsonResult. Рассмотрим пример.
[HttpGet]
public IActionResult GetNewtonsoftJson() =>
new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver()
});
Указание формата
Чтобы ограничить форматы ответа, примените фильтр [Produces]. Как и большинство фильтров, [Produces] можно применить к действию, контроллеру или глобальной области.
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
Предыдущий фильтр [Produces]:
- Заставляет все действия контроллера возвращать ответы в формате JSON для POCOs (обычных старых объектов CLR) или ObjectResult, а также их производных типов.
- Возвращает ответы в формате JSON, даже если настроены другие модули форматирования, а клиент задает другой формат.
Дополнительные сведения см. в статье Фильтры в ASP.NET Core.
Специальные форматировщики
Встроенные модули форматирования реализуют некоторые специальные возможности. По умолчанию типы возвращаемых значений string форматируются как text/plain (text/html, если того требует заголовок Accept). Это поведение можно отключить, удалив StringOutputFormatter. Форматировщики удаляются в Program.cs. Действия, у которых типом возвращаемого объекта является модель, возвращают ответ 204 No Content при возврате значения null. Это поведение можно отключить, удалив HttpNoContentOutputFormatter. Приведенный ниже код удаляет StringOutputFormatter и HttpNoContentOutputFormatter.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
Без StringOutputFormatter, встроенный модуль форматирования JSON форматирует типы возвращаемого значения string. Если встроенный модуль форматирования JSON удален и доступен модуль форматирования XML, то типы возвращаемого значения string форматирует модуль форматирования XML. В противном случае, string типы возвращаемого значения возвращают 406 Not Acceptable.
Без HttpNoContentOutputFormatter объекты со значением null форматируются с помощью настроенного модуля форматирования. Рассмотрим пример.
- Форматировщик JSON возвращает ответ с текстом
null. - Форматировщик XML возвращает пустой XML-элемент с атрибутом
xsi:nil="true".
Сопоставления URL-адресов для форматов ответа
Клиенты могут запрашивать определенный формат как часть URL-адреса, например:
- В строке запроса или в части пути.
- С использованием расширения файла конкретного формата, такого как XML или JSON.
Сопоставление из пути запроса должно быть указано в маршруте, используемом API. Рассмотрим пример.
[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
private readonly TodoItemStore _todoItemStore;
public TodoItemsController(TodoItemStore todoItemStore) =>
_todoItemStore = todoItemStore;
[HttpGet("{id:long}.{format?}")]
public TodoItem? GetById(long id) =>
_todoItemStore.GetById(id);
Предыдущий маршрут позволяет указать запрошенный формат с помощью дополнительного расширения файла. Атрибут [FormatFilter] проверяет наличие значения формата в RouteData и сопоставляет этот формат ответа с соответствующим форматировщиком при создании ответа.
| Route | Formatter |
|---|---|
/api/todoitems/5 |
Модуль форматирования вывода по умолчанию |
/api/todoitems/5.json |
Модуль форматирования JSON (если настроен) |
/api/todoitems/5.xml |
Модуль форматирования XML (если настроен) |
Полиморфная десериализация
Встроенные функции предоставляют ограниченный диапазон полиморфной сериализации, но совсем не поддерживают десериализацию. Для десериализации требуется настраиваемый преобразователь. Полный пример полиморфной десериализации см. в разделе "Полиморфная десериализация ".
Дополнительные ресурсы
Приложение MVC ASP.NET Core поддерживает форматирование данных ответа. Данные ответа могут возвращаться в определенных форматах или в формате, запрошенном клиентом.
Просмотреть или скачать образец кода (описание загрузки)
Результаты действий для конкретного формата
Некоторые типы результатов действий характерны для определенного формата, например JsonResult и ContentResult. Действия могут возвращать результаты в определенном формате независимо от настроек клиента. Например, при возврате JsonResult возвращаются данные в формате JSON. При возврате ContentResult или строки возвращаются строковые данные в формате обычного текста.
Действие не обязано возвращать данные конкретного типа. ASP.NET Core поддерживает любое возвращаемое значение объекта. Результаты действий, возвращающих объекты, которые не относятся к типу IActionResult, сериализуются с помощью соответствующей реализации IOutputFormatter. Дополнительные сведения см. в разделе "Типы возвращаемых действий контроллера" в веб-API ASP.NET Core.
Встроенный вспомогательный метод Ok возвращает данные в формате JSON:
// GET: api/authors
[HttpGet]
public ActionResult Get()
{
return Ok(_authors.List());
}
Скачанный пример возвращает список авторов. Использование инструментов разработчика браузера F12 или http-repl с предыдущим кодом:
- Отображается заголовок ответа, содержащий тип контента.
application/json; charset=utf-8 - Отобразятся заголовки запросов. Например, заголовок
Accept. Приведенный выше код игнорирует заголовокAccept.
Чтобы возвратить данные в формате обычного текста, используйте ContentResult и вспомогательный метод Content:
// GET api/authors/about
[HttpGet("About")]
public ContentResult About()
{
return Content("An API listing authors of docs.asp.net.");
}
В приведенном выше коде возвращаемым Content-Type является text/plain. Возврат строки приводит к Content-Type из text/plain:
// GET api/authors/version
[HttpGet("version")]
public string Version()
{
return "Version 1.0.0";
}
Для действий с несколькими возвращаемыми типами вернуть IActionResult. Например, возвращаются различные коды состояния HTTP на основе результатов выполненных операций.
Согласование содержимого
Согласование содержимого происходит, когда клиент задает заголовок Accept. Для ASP.NET Core по умолчанию используется формат JSON. Согласование содержимого:
- реализуется с помощью ObjectResult;
- встроено в результаты действия с определенным кодом состояния, возвращаемые из вспомогательных методов; Вспомогательные методы результатов действия основаны на
ObjectResult.
при возврате типа модели возвращаемым типом является ObjectResult.
Следующий метод действия использует вспомогательные методы Ok и NotFound:
// GET: api/authors/search?namelike=th
[HttpGet("Search")]
public IActionResult Search(string namelike)
{
var result = _authors.GetByNameSubstring(namelike);
if (!result.Any())
{
return NotFound(namelike);
}
return Ok(result);
}
По умолчанию ASP.NET Core поддерживает типы мультимедиа application/json, text/json и text/plain. Такие средства, как Fiddler или http-repl , могут задать Accept заголовок запроса, чтобы указать формат возврата. Если заголовок Accept содержит тип, который поддерживается сервером, возвращается этот тип. Сведения о добавлении дополнительных форматировщиков приведены в следующем разделе.
Действия контроллера могут возвращать POCO (Plain Old CLR Objects). При возвращении POCO среда выполнения автоматически создает ObjectResult, который создает оболочку вокруг объекта. Клиент получает отформатированный сериализованный объект. Если возвращаемый объект имеет значение null, возвращается ответ 204 No Content.
Возвращение типа объекта:
// GET api/authors/RickAndMSFT
[HttpGet("{alias}")]
public Author Get(string alias)
{
return _authors.GetByAlias(alias);
}
В приведенном выше коде запрос допустимого псевдонима автора получает ответ 200 OK с данными об авторе. Запрос недопустимого псевдонима возвращает ответ 204 No Content.
Заголовок Accept
Согласование содержимого выполняется только при наличии в запросе заголовка Accept. Если запрос содержит заголовок Accept, ASP.NET Core:
- перечисляет типы мультимедиа в заголовке Accept в порядке предпочтения;
- пытается найти форматировщик, который может создать ответ в одном из указанных форматов.
Если форматировщик, который может удовлетворить запрос клиента, не найден, ASP.NET Core:
- Возвращает значение
406 Not Acceptable, если MvcOptions.ReturnHttpNotAcceptable задано значениеtrue, или - - пытается найти первый форматировщик, который может создать ответ.
Если форматировщик, обеспечивающий требуемый формат, не настроен, используется первый форматировщик, способный отформатировать данный объект. Если в запросе не отображается заголовок Accept:
- Для сериализации ответа используется первый форматировщик, который может работать с объектом.
- Переговоры не ведутся. Сервер определяет возвращаемый формат.
Если заголовок Accept содержит */*, он игнорируется, если только RespectBrowserAcceptHeader не имеет значение true в MvcOptions.
Браузеры и согласование содержимого
В отличие от обычных клиентов API, веб-браузеры предоставляют заголовки Accept. Веб-браузеры указывают множество форматов, включая подстановочные знаки. Если платформа обнаруживает, что запрос поступает из браузера, по умолчанию выполняется следующее:
- Заголовок
Acceptигнорируется. - Содержимое возвращается с помощью первого зарегистрированного средства форматирования выходных данных, который может обрабатывать тип ответа, если иное не настроено.
Этот подход обеспечивает более согласованный интерфейс в браузерах при использовании API.
Чтобы настроить приложение для учета заголовков Accept в браузере, установите для параметра RespectBrowserAcceptHeader значение true:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // false by default
});
}
Настройка форматировщиков
В приложениях, которым требуется поддержка дополнительных форматов, можно добавлять соответствующие пакеты NuGet и настраивать поддержку. Существуют отдельные модули форматирования для ввода и вывода. Форматировщики ввода используются в привязке модели. Форматировщики вывода используются для форматирования ответов. Сведения о создании пользовательского форматировщика см. в статье Пользовательские модули форматирования для веб-API в ASP.NET Core.
Добавление поддержки формата XML
Форматировщики XML, реализованные с помощью XmlSerializer, можно настроить путем вызова AddXmlSerializerFormatters:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddXmlSerializerFormatters();
}
Приведенный выше код сериализует результаты с помощью XmlSerializer.
При использовании приведенного выше кода методы контроллера возвращают соответствующий формат на основе заголовка Accept запроса.
Настройка форматировщиков, основанных на System.Text.Json
Возможности форматировщиков на основе System.Text.Json можно настроить с помощью Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. Форматирование по умолчанию — camelCase. Следующий выделенный код задает форматирование PascalCase:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddJsonOptions(options =>
options.JsonSerializerOptions.PropertyNamingPolicy = null);
}
Для вызова метода действия ControllerBase.Problem для создания ответа ProblemDetails, используется следующий порядок выполнения:
[HttpGet("error")]
public IActionResult GetError()
{
return Problem("Something went wrong!");
}
Приведенный выше код:
-
https://localhost:5001/WeatherForecast/temperatureвозвращает PascalCase. -
https://localhost:5001/WeatherForecast/errorвозвращает camelCase. Ответ на ошибку всегда в формате camelCase, даже если приложение задает формат PascalCase.ProblemDetailsсоответствует RFC 7807, где указывается использование нижнего регистра
Следующий код задает PascalCase и добавляет пользовательский преобразователь:
services.AddControllers().AddJsonOptions(options =>
{
// Use the default property (Pascal) casing.
options.JsonSerializerOptions.PropertyNamingPolicy = null;
// Configure a custom converter.
options.JsonSerializerOptions.Converters.Add(new MyCustomJsonConverter());
});
Параметры сериализации выходных данных для отдельных действий можно настроить с помощью JsonResult. Рассмотрим пример.
public IActionResult Get()
{
return Json(model, new JsonSerializerOptions
{
WriteIndented = true,
});
}
Поддержка JSON-формата, основанного на библиотеке Newtonsoft.Json
Форматировщики JSON по умолчанию основаны на System.Text.Json. Поддержка форматировщиков и функций на основе Newtonsoft.Json доступна при установке пакета NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson и его настройке в Startup.ConfigureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson();
}
В приведенном выше коде вызов AddNewtonsoftJson настраивает следующие функции веб-API, MVC и Razor Pages для использования Newtonsoft.Json:
- Методы форматирования входных и выходных данных, которые считывают и записывают JSON
- JsonResult
- Исправление JSON
- IJsonHelper
- TempData
Возможно, некоторые функции не будут оптимально работать с форматировщиками на основе System.Text.Json и будут требовать ссылки на форматировщики на основе Newtonsoft.Json. Продолжайте использовать форматы на основе Newtonsoft.Json, когда приложение:
- Использует атрибут
Newtonsoft.Json. Например,[JsonProperty]или[JsonIgnore]. - Настраивает параметры сериализации.
- Зависит от функций, предоставляемых
Newtonsoft.Json.
Функции для форматировщиков на основе Newtonsoft.Json можно настроить с помощью Microsoft.AspNetCore.Mvc.MvcNewtonsoftJsonOptions.SerializerSettings:
services.AddControllers().AddNewtonsoftJson(options =>
{
// Use the default property (Pascal) casing
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
// Configure a custom converter
options.SerializerSettings.Converters.Add(new MyCustomJsonConverter());
});
Параметры сериализации выходных данных для отдельных действий можно настроить с помощью JsonResult. Рассмотрим пример.
public IActionResult Get()
{
return Json(model, new JsonSerializerSettings
{
Formatting = Formatting.Indented,
});
}
Указание формата
Чтобы ограничить форматы ответа, примените фильтр [Produces]. Как и большинство фильтров, [Produces] можно применить к действию, контроллеру или глобальной области.
[ApiController]
[Route("[controller]")]
[Produces("application/json")]
public class WeatherForecastController : ControllerBase
{
Предыдущий фильтр [Produces]:
- Принуждает все действия контроллера возвращать ответы в формате JSON для обычных старых объектов CLR (POCOs) или ObjectResult и их производных типов.
- Если другие форматировщики настроены и клиент указывает другой формат, возвращается JSON.
Дополнительные сведения см. в статье Фильтры в ASP.NET Core.
Специальные форматировщики
Встроенные модули форматирования реализуют некоторые специальные возможности. По умолчанию типы возвращаемых значений string форматируются как text/plain (text/html, если того требует заголовок Accept). Это поведение можно отключить, удалив StringOutputFormatter. Форматировщики удаляются в методе ConfigureServices. Действия, у которых типом возвращаемого объекта является модель, возвращают ответ 204 No Content при возврате значения null. Это поведение можно отключить, удалив HttpNoContentOutputFormatter. Приведенный ниже код удаляет StringOutputFormatter и HttpNoContentOutputFormatter.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers(options =>
{
// requires using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
}
Без StringOutputFormatter, встроенный модуль форматирования JSON форматирует типы возвращаемого значения string. Если встроенный модуль форматирования JSON удален и доступен модуль форматирования XML, то типы возвращаемого значения string форматирует модуль форматирования XML. В противном случае, string типы возвращаемого значения возвращают 406 Not Acceptable.
Без HttpNoContentOutputFormatter объекты со значением null форматируются с помощью настроенного модуля форматирования. Рассмотрим пример.
- Форматировщик JSON возвращает ответ с текстом
null. - Форматировщик XML возвращает пустой XML-элемент с атрибутом
xsi:nil="true".
Сопоставления URL-адреса для формата ответа
Клиенты могут запрашивать определенный формат как часть URL-адреса, например:
- В строке запроса или в части пути.
- С использованием расширения файла конкретного формата, такого как XML или JSON.
Сопоставление из пути запроса должно быть указано в маршруте, используемом API. Рассмотрим пример.
[Route("api/[controller]")]
[ApiController]
[FormatFilter]
public class ProductsController : ControllerBase
{
[HttpGet("{id}.{format?}")]
public Product Get(int id)
{
Этот маршрут позволяет задать запрошенный формат в качестве дополнительного расширения файла. Атрибут [FormatFilter] проверяет наличие значения формата в RouteData и сопоставляет этот формат ответа с соответствующим форматировщиком при создании ответа.
| Route | Formatter |
|---|---|
/api/products/5 |
Модуль форматирования вывода по умолчанию |
/api/products/5.json |
Модуль форматирования JSON (если настроен) |
/api/products/5.xml |
Модуль форматирования XML (если настроен) |
ASP.NET Core MVC поддерживает форматирование данных ответа, используя указанные форматы или в ответ на запрос клиента.
Результаты действий для конкретного формата
Некоторые типы результатов действий характерны для определенного формата, например JsonResult и ContentResult. Действия могут возвращать результаты, которые всегда используют указанный формат, игнорируя запрос клиента для другого формата. Например, возврат JsonResult возвращает данные в формате JSON, а возврат ContentResult возвращает строковые данные в формате обычного текста.
Действию не обязательно возвращать данные определенного типа. ASP.NET Core поддерживает любое возвращаемое значение объекта. Результаты действий, возвращающих объекты, не являющиеся типами IActionResult, сериализуются с помощью соответствующей реализации IOutputFormatter. Дополнительные сведения см. в разделе "Типы возвращаемых действий контроллера" в веб-API ASP.NET Core.
По умолчанию встроенный вспомогательный метод ControllerBase.Ok возвращает данные в формате JSON:
[HttpGet]
public IActionResult Get()
=> Ok(_todoItemStore.GetList());
Пример кода возвращает список элементов Todo. С помощью средств разработчика браузера F12 или http-repl с предыдущим кодом отображается следующее:
- Заголовок ответа, содержащий тип контента:
application/json; charset=utf-8 - Заголовки запроса. Например, заголовок
Accept. Приведенный выше код игнорирует заголовокAccept.
Чтобы возвратить данные в формате обычного текста, используйте ContentResult и вспомогательный метод Content:
[HttpGet("Version")]
public ContentResult GetVersion()
=> Content("v1.0.0");
В приведенном выше коде возвращаемым Content-Type является text/plain.
Для действий с несколькими возвращаемыми типами данных используйте IActionResult. Например, при возврате различных кодов состояния HTTP в зависимости от результата операции.
Согласование содержимого
Согласование содержимого происходит, когда клиент задает заголовок Accept. Для ASP.NET Core по умолчанию используется формат JSON. Согласование содержимого:
- реализуется с помощью ObjectResult;
- встроено в результаты действия с определенным кодом состояния, возвращаемые из вспомогательных методов; Вспомогательные методы результатов действия основаны на
ObjectResult.
при возврате типа модели возвращаемым типом является ObjectResult.
Следующий метод действия использует вспомогательные методы Ok и NotFound:
[HttpGet("{id:long}")]
public IActionResult GetById(long id)
{
var todo = _todoItemStore.GetById(id);
if (todo is null)
{
return NotFound();
}
return Ok(todo);
}
По умолчанию ASP.NET Core поддерживает следующие типы носителей:
application/jsontext/jsontext/plain
Такие средства, как Fiddler или http-repl , могут задать Accept заголовок запроса, чтобы указать формат возврата. Если заголовок Accept содержит тип, который поддерживается сервером, возвращается этот тип. Сведения о добавлении дополнительных форматировщиков приведены в следующем разделе.
Действия контроллера могут возвращать POCO (простые объекты CLR). При возвращении POCO среда выполнения автоматически создает ObjectResult, который создает оболочку для объекта. Клиент получает отформатированный сериализованный объект. Если возвращаемый объект имеет значение null, возвращается ответ 204 No Content.
В следующем примере возвращается тип объекта:
[HttpGet("{id:long}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
В приведенном выше коде запрос допустимого элемента todo возвращает 200 OK ответ. Запрос невалидного элемента todo возвращает ответ типа 204 No Content.
Заголовок Accept
Согласование содержимого выполняется только при наличии в запросе заголовка Accept. Если запрос содержит заголовок Accept, ASP.NET Core:
- перечисляет типы мультимедиа в заголовке Accept в порядке предпочтения;
- пытается найти форматировщик, который может создать ответ в одном из указанных форматов.
Если форматировщик, который может удовлетворить запрос клиента, не найден, ASP.NET Core:
- Возвращает значение
406 Not Acceptable, если MvcOptions.ReturnHttpNotAcceptable задано значениеtrue, или - - Пытается найти первый форматировщик, который может создать ответ.
Если форматировщик, обеспечивающий требуемый формат, не настроен, используется первый форматировщик, способный отформатировать данный объект. Если в запросе не отображается заголовок Accept:
- Для сериализации ответа используется первый форматировщик, который может работать с объектом.
- Переговоры не происходят. Сервер определяет возвращаемый формат.
Если заголовок Accept содержит */*, он игнорируется, если только RespectBrowserAcceptHeader не имеет значение true в MvcOptions.
Браузеры и согласование содержимого
В отличие от обычных клиентов API, веб-браузеры предоставляют заголовки Accept. Веб-браузеры указывают множество форматов, включая подстановочные знаки. Если платформа обнаруживает, что запрос поступает из браузера, по умолчанию выполняется следующее:
- Заголовок
Acceptигнорируется. - Содержимое возвращается с помощью первого зарегистрированного средства форматирования выходных данных, который может обрабатывать тип ответа, если иное не настроено.
Этот подход обеспечивает более согласованный интерфейс в браузерах при использовании API.
Чтобы настроить приложение для соблюдения заголовков браузера, задайте значение true для свойства RespectBrowserAcceptHeader.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true;
});
Настройка форматировщиков
Приложения, которые должны поддерживать дополнительные форматы, могут добавлять соответствующие пакеты NuGet и настраивать поддержку. Существуют отдельные модули форматирования для ввода и вывода. Форматировщики ввода используются в привязке модели. Форматировщики вывода используются для форматирования ответов. Сведения о создании пользовательского форматировщика см. в статье Пользовательские модули форматирования для веб-API в ASP.NET Core.
Добавление поддержки формата XML
Чтобы настроить XML-форматировщики, реализованные с помощью XmlSerializer, вызовите AddXmlSerializerFormatters.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddXmlSerializerFormatters();
При использовании приведенного выше кода методы контроллера возвращают соответствующий формат на основе заголовка Accept запроса.
Настройка форматировщиков на основе System.Text.Json
Чтобы настроить функцию для форматировщиков на основе System.Text.Json, используйте Microsoft.AspNetCore.Mvc.JsonOptions.JsonSerializerOptions. Выделенный ниже код задает форматирование PascalCase вместо стиля camelCase по умолчанию.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
Чтобы настроить параметры сериализации выходных данных для определенных действий, используйте JsonResult. Рассмотрим пример.
[HttpGet]
public IActionResult Get()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerOptions { PropertyNamingPolicy = null });
Добавьте поддержку формата JSON на основе Newtonsoft.Json.
JSON форматировщики по умолчанию используют System.Text.Json. Чтобы использовать средства форматирования на основе Newtonsoft.Json, установите пакет NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson и настройте его в Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddNewtonsoftJson();
В приведенном выше коде вызов AddNewtonsoftJson настраивает следующие функции веб-API, MVC и Razor Pages для использования Newtonsoft.Json:
- Методы форматирования входных и выходных данных, которые считывают и записывают JSON
- JsonResult
- Исправление JSON
- IJsonHelper
- TempData
Возможно, некоторые функции не будут оптимально работать с форматировщиками на основе System.Text.Json и будут требовать ссылки на форматировщики на основе Newtonsoft.Json. Продолжайте использовать форматы на основе Newtonsoft.Json, когда приложение:
- Использует атрибут
Newtonsoft.Json. Например,[JsonProperty]или[JsonIgnore]. - Настраивает параметры сериализации.
- Зависит от функций, предоставляемых
Newtonsoft.Json.
Чтобы настроить функции форматировщиков на основе Newtonsoft.Json, используйте SerializerSettings.
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
Чтобы настроить параметры сериализации выходных данных для определенных действий, используйте JsonResult. Рассмотрим пример.
[HttpGet]
public IActionResult GetNewtonsoftJson()
=> new JsonResult(
_todoItemStore.GetList(),
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() });
Формат ProblemDetails и ValidationProblemDetails ответов
Следующий метод действия вызывает ControllerBase.Problem для создания ProblemDetails ответа:
[HttpGet("Error")]
public IActionResult GetError()
=> Problem("Something went wrong.");
ProblemDetails Ответ всегда в формате camelCase, даже если приложение задает формат PascalCase.
ProblemDetails
следует RFC 7807, который определяет использование нижнего регистра.
[ApiController] Если атрибут применяется к классу контроллера, контроллер создает ValidationProblemDetails ответ при сбое проверки модели. Этот ответ содержит словарь, который использует имена свойств модели без изменений в качестве ключей ошибок. Например, следующая модель включает одно свойство, требующее проверки:
public class SampleModel
{
[Range(1, 10)]
public int Value { get; set; }
}
По умолчанию ValidationProblemDetails ответ, возвращаемый, когда свойство Value является недопустимым, использует ключ ошибки Value, как показано в следующем примере:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-00000000000000000000000000000000-000000000000000-00",
"errors": {
"Value": [
"The field Value must be between 1 and 10."
]
}
}
Чтобы отформатировать имена свойств, используемые в качестве ключей ошибок IMetadataDetailsProvider, добавьте реализацию IMetadataDetailsProvider в коллекцию MvcOptions.ModelMetadataDetailsProviders. В следующем примере добавляется реализация на основе System.Text.Json, SystemTextJsonValidationMetadataProvider, которая по умолчанию форматирует имена свойств в стиле camelCase.
builder.Services.AddControllers();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new SystemTextJsonValidationMetadataProvider());
});
SystemTextJsonValidationMetadataProvider также принимает реализацию JsonNamingPolicy в конструкторе, которая задает настраиваемую политику именования для форматирования имен свойств.
Чтобы задать настраиваемое имя свойства в модели, используйте атрибут [JsonPropertyName] для свойства:
public class SampleModel
{
[Range(1, 10)]
[JsonPropertyName("sampleValue")]
public int Value { get; set; }
}
Ответ ValidationProblemDetails, возвращаемый для предыдущей модели, когда свойство Value недопустимо, использует ключ ошибки sampleValue, как показано в следующем примере:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-00000000000000000000000000000000-000000000000000-00",
"errors": {
"sampleValue": [
"The field Value must be between 1 and 10."
]
}
}
Чтобы отформатировать ValidationProblemDetails ответ, используйте Newtonsoft.JsonNewtonsoftJsonValidationMetadataProvider:
builder.Services.AddControllers()
.AddNewtonsoftJson();
builder.Services.Configure<MvcOptions>(options =>
{
options.ModelMetadataDetailsProviders.Add(
new NewtonsoftJsonValidationMetadataProvider());
});
По умолчанию NewtonsoftJsonValidationMetadataProvider форматирует имена свойств в camelCase.
NewtonsoftJsonValidationMetadataProvider также принимает реализацию NamingPolicy в конструкторе, которая задает настраиваемую политику именования для форматирования имен свойств. Чтобы задать пользовательское имя свойства в модели, используйте атрибут [JsonProperty].
Указание формата
Чтобы ограничить форматы ответа, примените фильтр [Produces]. Как и большинство фильтров, [Produces] можно применить к действию, контроллеру или глобальной области.
[ApiController]
[Route("api/[controller]")]
[Produces("application/json")]
public class TodoItemsController : ControllerBase
Предыдущий фильтр [Produces]:
- Принуждает все действия контроллера возвращать ответы в формате JSON для POCO (обычные старые объекты CLR) или их производных типов ObjectResult.
- Возвращает ответы в формате JSON, даже если настроены другие модули форматирования, а клиент задает другой формат.
Дополнительные сведения см. в статье Фильтры в ASP.NET Core.
Специальные форматировщики
Встроенные модули форматирования реализуют некоторые специальные возможности. По умолчанию типы возвращаемых значений string форматируются как text/plain (text/html, если того требует заголовок Accept). Это поведение можно отключить, удалив StringOutputFormatter. Форматировщики удаляются в Program.cs. Действия, у которых типом возвращаемого объекта является модель, возвращают ответ 204 No Content при возврате значения null. Это поведение можно отключить, удалив HttpNoContentOutputFormatter. Приведенный ниже код удаляет StringOutputFormatter и HttpNoContentOutputFormatter.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
// using Microsoft.AspNetCore.Mvc.Formatters;
options.OutputFormatters.RemoveType<StringOutputFormatter>();
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
Без StringOutputFormatter, встроенный модуль форматирования JSON форматирует типы возвращаемого значения string. Если встроенный модуль форматирования JSON удален и доступен модуль форматирования XML, то типы возвращаемого значения string форматирует модуль форматирования XML. В противном случае, string типы возвращаемого значения возвращают 406 Not Acceptable.
Без HttpNoContentOutputFormatter объекты со значением null форматируются с помощью настроенного модуля форматирования. Рассмотрим пример.
- Форматировщик JSON возвращает ответ с текстом
null. - Форматировщик XML возвращает пустой XML-элемент с атрибутом
xsi:nil="true".
Сопоставления URL-адреса для формата ответа
Клиенты могут запрашивать определенный формат как часть URL-адреса, например:
- В строке запроса или в части пути.
- С использованием расширения файла конкретного формата, такого как XML или JSON.
Сопоставление из пути запроса должно быть указано в маршруте, используемом API. Рассмотрим пример.
[ApiController]
[Route("api/[controller]")]
[FormatFilter]
public class TodoItemsController : ControllerBase
{
private readonly TodoItemStore _todoItemStore;
public TodoItemsController(TodoItemStore todoItemStore)
=> _todoItemStore = todoItemStore;
[HttpGet("{id:long}.{format?}")]
public TodoItem? GetById(long id)
=> _todoItemStore.GetById(id);
Предыдущий маршрут позволяет указать запрошенный формат с помощью дополнительного расширения файла. Атрибут [FormatFilter] проверяет наличие значения формата в RouteData и сопоставляет этот формат ответа с соответствующим форматировщиком при создании ответа.
| Route | Formatter |
|---|---|
/api/todoitems/5 |
Модуль форматирования вывода по умолчанию |
/api/todoitems/5.json |
Модуль форматирования JSON (если настроен) |
/api/todoitems/5.xml |
Модуль форматирования XML (если настроен) |
Полиморфная десериализация
Встроенные функции предоставляют ограниченный диапазон полиморфной сериализации, но совсем не поддерживают десериализацию. Для десериализации требуется настраиваемый преобразователь. Полный пример полиморфной десериализации см. в разделе "Полиморфная десериализация ".
Дополнительные ресурсы
ASP.NET Core