Используя более новую веб-API ASP.NET , в Chrome Я вижу XML - как я могу изменить его на запрос JSON <75505444165>, чтобы просмотреть 41> в браузере? Я действительно считаю, что это всего лишь часть заголовков запроса, я прав?
Как заставить веб-API ASP.NET возвращать JSON вместо XML с помощью Chrome?
Ответы (29)
Примечание. Прочтите комментарии к этому ответу, он может вызвать уязвимость XSS, если вы используете обработку ошибок по умолчанию для WebAPI
Я просто добавляю следующее в класс App_Start / WebApiConfig.cs
в свой проект MVC Web API .
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html") );
Это гарантирует, что вы получите JSON для большинства запросов, но вы можете получить XML
при отправке text/xml
.
Если вам нужен ответ Content-Type
как application/json
, проверьте ответ Тодда ниже.
NameSpace
использует System.Net.Http.Headers
.
Это удивительно недооцененный ответ, и хотя исходный вопрос не был полностью ясен, это напрямую делает JSON ответом по умолчанию для веб-браузера (который отправляет Accept: text / html). Молодец.
Мне это нравится намного больше, чем требование параметра запроса json = true.
+1 Однозначно лучший ответ. Я полагаю, что есть масса людей, которые решают полностью удалить XML только потому, что они не видят JSON в браузере.
Отличная работа. Мой ответ немного расширяет это, принимая text / html, но возвращая application / json, на случай, если вы используете расширение Chrome, которое ожидает его для форматирования.
@Felipe: Вы добавили свою строку выше в Global.asax? Вы имеете в виду: GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
?
Я давно не работал с Web API, но уверен, что это так.
Когда я это сделал, я обнаружил, что данные, предоставленные третьей стороной с тегами разрыва HTML, заканчиваются возвратом каретки. Тогда JSON был недействительным. Лучше использовать принятый ответ, если вас это беспокоит.
Обратите внимание, что заголовок ответа Content-Type
по-прежнему будет text/html
.
почему текст / html? Разве это не тип для json: application / json? Когда я использовал решение выше и поместил application / json вместо text / html, я получил ответ в XML. Разве этот счетчик не интуитивно понятен? application / json должно было работать. В чем причина этого?
Это ужасно. Заголовок типа содержимого ответа должен быть application / json. Это «решение» делает его text / html.
Это было решение для отображения на хроме. Хотя он и не идеален, он подходит, но если вам нужен Content-Type как application / json, вы можете проверить ответ Тодда.
Обратите внимание, что если в поле заголовка запроса «Accept» указано «application / json» (т.е. установлено в запросе ajax GET), он должен вернуть json. Mine делает это, но отображает xml, если вы открываете URL-адрес в chrome (где для подтверждения запроса не установлено значение json).
В моем случае конфигурация не требовалась. По умолчанию использовалась json-сериализация. В соответствии с правилами согласования контента, если нет соглашения, контент будет преобразован в json.
Если вы хотите заблокировать только json, я предлагаю вам очистить все форматеры и включить только Json. GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
Меня раздражает, что Stack Overflow не позволяет мне отозвать свой голос, потому что это не то, что я ищу. Верблюд, вероятно, потому, что люди бросают вызов, думая, что это решение правильное. Почему MS не настраивает это должным образом с помощью JSON по умолчанию? Я сделал это через сертифицированный класс Microsoft и постараюсь найти подходящее решение.
Почему / как JSON поддерживает HTML?
Только 40 человек заметили, что есть способ получше. (через @meffect просто переназначьте тип ответа вместо установки неправильного значения по умолчанию.)
Это глупый взлом, а не хороший ответ. Зачем изменять свой код для чего-то настолько простого, как установка заголовка запроса? Если вы так увлечены написанием кода для этого, рекомендуем писать тесты. И я предполагаю, что Наспински и другие поняли, что они не могут тестировать POST, PUT, DELETE и т. Д. С помощью простого браузера.
Этот ответ потенциально может раскрыть уязвимость XSS. WebAPI будет включать полный URL-адрес в ответ 404, и поскольку тип содержимого - text / html, браузер с радостью выполнит любой JavaScript, включенный в строку запроса.
Подробную конфигурацию можно найти по ссылке: docs.microsoft.com/en-us/aspnet/web-api/overview/…
Я согласен с @meffect, это "прекрасный" ответ для среды разработки, но если вы используете это решение в производственной среде, вы подвергнетесь атакам XSS.
Почему так много разработчиков, использующих MS, согласны с хакерскими ответами? Ваш веб-клиент будет получать ответы, несовместимые с запрошенным форматом. Когда вы запрашиваете text / html, вы должны получать HTML. Когда вы запрашиваете application / json, вы должны получить обратно JSON. Шиш.
Как указывали другие, это вызывает уязвимость XSS на странице веб-api 404, поскольку URL-адрес, вызывающий 404, включен в качестве содержимого на странице ошибки 404. НЕ ИСПОЛЬЗУЙТЕ.
Используя ответ Фелипе Леусина в течение многих лет, после недавнего обновления основных библиотек и Json.Net я столкнулся с System.MissingMethodException
: SupportedMediaTypes.
В моем случае решение, которое, надеюсь, будет полезным для других, столкнувшихся с таким же непредвиденным исключением, - это установить System.Net.Http
. NuGet, по-видимому, удаляет его при некоторых обстоятельствах. После ручной установки проблема была решена.
Вы можете использовать как показано ниже:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
Если вы создаете приложение веб-API для простой передачи сообщений JSON, рассмотрите этот ответ.
Я удивлен, увидев так много ответов, требующих кодирования для изменения одного варианта использования (GET) в одного API вместо использования подходящего инструмента, который нужно установить один раз и который можно использовать для любой API (собственный или сторонний) и все варианты использования.
Итак, хороший ответ:
- Если вы хотите запросить только json или другой тип контента, установите Requestly или аналогичный инструмент и измените заголовок Accept.
- Если вы хотите также использовать POST и иметь хорошо отформатированный json, xml и т. Д., Используйте подходящее расширение для тестирования API, например Postman или ARC. .
Некоторые предпочитают делать что-то, не добавляя лишних инструментов и библиотек.
По-прежнему неправильно вносить изменения в API только потому, что кто-то использует не тот инструмент для работы. Веб-браузер не предназначен для тестирования API, даже не для просмотра вывода API, а для просмотра документов. Еще хуже, если кто-то думает, что инструмент для тестирования API - это раздутый инструмент, а не часть обязательного набора инструментов для любого разработчика API, и, честно говоря, я бы также добавил разработчиков интерфейса, потому что им также нужно взаимодействовать и экспериментировать с API. Вероятно, этого также недостаточно, потому что браузер без надстроек не позволяет устанавливать заголовки, отправлять сообщения в API или даже проверять заголовки ответов.
Я понимаю, что вы говорите, и вы не ошиблись. Но не по теме, причина, по которой вас отвергают, - это тон, которым вы отвечаете на вопрос. Вы говорите очень агрессивно и производите впечатление разработчика, который думает, что знает все, а это очень неприятно. Я уверен, что вы отличный разработчик, судя по вашим отзывам. Но вы должны научиться, особенно в такой профессиональной среде QA, обращаться к людям и убеждать их более дружелюбно и по-человечески. Возможно, сначала дайте ответ, который они хотят, затем объясните лучший способ и мотивируйте, почему он лучше.
config.Formatters.Remove(config.Formatters.XmlFormatter);
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, как и / или почему он решает проблему, улучшит долгосрочную ценность ответа. Пожалуйста, прочтите этот coderhelper.com/help/how-to-answer
Большинство приведенных выше ответов имеют смысл. Поскольку вы видите, что данные форматируются в формате XML, это означает, что применяется средство форматирования XML, поэтому вы можете увидеть формат JSON, просто удалив XMLFormatter из параметра HttpConfiguration, например
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.EnableSystemDiagnosticsTracing();
}
, поскольку JSON является форматом по умолчанию
Возвращение правильного формата выполняется средством форматирования медиа-типа.
Как уже упоминалось, вы можете сделать это в классе WebApiConfig
:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
...
// Configure Web API to return JSON
config.Formatters.JsonFormatter
.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));
...
}
}
Для получения дополнительной информации проверьте:
- Средства форматирования мультимедиа в веб-API ASP.NET 2.
- Согласование содержимого в веб-API ASP.NET.
Если ваши действия возвращают XML (что является случаем по умолчанию) и вам нужен только определенный метод для возврата JSON, вы можете затем использовать ActionFilterAttribute
и применить его к этому конкретному действию.
Атрибут фильтра:
public class JsonOutputAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
var value = content.Value;
Type targetType = actionExecutedContext.Response.Content.GetType().GetGenericArguments()[0];
var httpResponseMsg = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
RequestMessage = actionExecutedContext.Request,
Content = new ObjectContent(targetType, value, new JsonMediaTypeFormatter(), (string)null)
};
actionExecutedContext.Response = httpResponseMsg;
base.OnActionExecuted(actionExecutedContext);
}
}
Применение к действию:
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
return _repository.AllPersons(); // the returned output will be in JSON
}
Обратите внимание, что вы можете опустить слово Attribute
на оформлении действия и использовать только [JsonOutput]
вместо [JsonOutputAttribute]
.
Просто добавьте эти две строки кода в свой WebApiConfig класс
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//add this two line
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
............................
}
}
согласно последней версии ASP.net WebApi 2,
под WebApiConfig.cs
, это будет работать
config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
WebApiConfig - это место, где вы можете настроить, хотите ли вы выводить в json или xml. По умолчанию это xml. В функции регистрации мы можем использовать HttpConfiguration Formatters для форматирования вывода.
System.Net.Http.Headers => MediaTypeHeaderValue("text/html")
необходим для получения вывода в формате json.
Вот самый простой способ, который я использовал в своих приложениях. Добавьте указанные ниже 3 строки кода в App_Start\\WebApiConfig.cs
в Register
функцию
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
Веб-API Asp.net автоматически сериализует ваш возвращаемый объект в JSON, и поскольку application/json
добавляется в заголовок, браузер или получатель поймут, что вы возвращаете результат JSON.
Просто измените App_Start/WebApiConfig.cs
следующим образом:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
//Below formatter is used for returning the Json result.
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
//Default route
config.Routes.MapHttpRoute(
name: "ApiControllerOnly",
routeTemplate: "api/{controller}"
);
}
Удаление форматтера, как правило, не является хорошей идеей, вы удаляете функциональность.
На самом деле в этом случае у меня это работает хорошо, также многие другие предлагают такой способ. Я узнал об этом из книги myview.rahulnivi.net/building-spa-angular-mvc-5!
Вот решение, аналогичное jayson.centeno и другим ответам, но с использованием встроенного расширения из System.Net.Http.Formatting
.
public static void Register(HttpConfiguration config)
{
// add support for the 'format' query param
// cref: http://blogs.msdn.com/b/hongyes/archive/2012/09/02/support-format-in-asp-net-web-api.aspx
config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");
// ... additional configuration
}
Решение было в первую очередь ориентировано на поддержку формата $ для OData в ранних версиях WebApi, но оно также применимо к реализации без OData и возвращает
Content-Type: application/json; charset=utf-8
заголовок в ответе.
Он позволяет вам добавить &$format=json
или &$format=xml
в конец вашего uri при тестировании в браузере. Это не влияет на другое ожидаемое поведение при использовании клиента, отличного от браузера, где вы можете установить свои собственные заголовки.
Прошло некоторое время с тех пор, как этот вопрос был задан (и дан ответ), но другой вариант - переопределить заголовок Accept на сервере во время обработки запроса с помощью MessageHandler, как показано ниже:
public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var someOtherCondition = false;
var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
if (someOtherCondition && accHeader.Contains("application/xml"))
{
request.Headers.Remove("Accept");
request.Headers.Add("Accept", "application/json");
}
return await base.SendAsync(request, cancellationToken);
}
}
Где someOtherCondition
может быть любым, включая тип браузера и т. Д. Это будет для условных случаев, когда только иногда мы хотим переопределить согласование содержимого по умолчанию. В противном случае, согласно другим ответам, вы просто удалите ненужное средство форматирования из конфигурации.
Вам, конечно же, нужно будет его зарегистрировать. Вы можете сделать это глобально:
public static void Register(HttpConfiguration config) {
config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
}
или по маршруту за маршрутом:
config.Routes.MapHttpRoute(
name: "SpecialContentRoute",
routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
constraints: null,
handler: new ForceableContentTypeDelegationHandler()
);
И поскольку это обработчик сообщений, он будет работать как на стороне запроса, так и на стороне ответа конвейера, как и HttpModule
. Таким образом, вы можете легко подтвердить переопределение с помощью настраиваемого заголовка:
public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
var wasForced = false;
var someOtherCondition = false;
var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
if (someOtherCondition && accHeader.Contains("application/xml"))
{
request.Headers.Remove("Accept");
request.Headers.Add("Accept", "application/json");
wasForced = true;
}
var response = await base.SendAsync(request, cancellationToken);
if (wasForced){
response.Headers.Add("X-ForcedContent", "We overrode your content prefs, sorry");
}
return response;
}
}
Мне непонятно, почему в ответе столько сложности. Конечно, есть много способов сделать это с помощью QueryStrings, заголовков и параметров ... но то, что я считаю лучшей практикой, просто. Вы запрашиваете простой URL-адрес (например, http://yourstartup.com/api/cars
), а взамен получаете JSON. Вы получаете JSON с правильным заголовком ответа:
Content-Type: application/json
В поисках ответа на этот же вопрос я нашел эту ветку, и мне пришлось продолжить, потому что принятый ответ не работает точно. Я нашел ответ, который, как мне кажется, слишком прост, чтобы быть лучшим:
Установить форматировщик WebAPI по умолчанию
Я тоже добавлю сюда свой совет.
WebApiConfig.cs
namespace com.yourstartup
{
using ...;
using System.Net.Http.Formatting;
...
config.Formatters.Clear(); //because there are defaults of XML..
config.Formatters.Add(new JsonMediaTypeFormatter());
}
У меня действительно есть вопрос, откуда берутся значения по умолчанию (по крайней мере, те, которые я вижу). Являются ли они значениями .NET по умолчанию или, возможно, созданы где-то еще (кем-то другим в моем проекте). Всегда, надеюсь, это поможет.
Из MSDN Создание одностраничного приложения с ASP.NET и AngularJS (примерно 41 минута).
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// ... possible routing etc.
// Setup to return json and camelcase it!
var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
formatter.SerializerSettings.ContractResolver =
new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
}
Он должен быть актуальным, я попробовал, и он сработал.
Использование RequestHeaderMapping работает еще лучше, потому что оно также устанавливает Content-Type = application/json
в заголовке ответа, что позволяет Firefox (с надстройкой JSONView) форматировать ответ как JSON.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept",
"text/html",
StringComparison.InvariantCultureIgnoreCase,
true,
"application/json"));
Это наиболее экономичное и простое решение, и Fiddler также определяет тип содержимого, возвращаемый как josn.
Отлично! Где бы вы посоветовали поместить это в код?
Он должен быть в WebApiConfig.cs
Также отличное исправление для расширения jsonformatter, которое ломается без этого.
по какой-то причине расширение форматирования jsonp ломается, хотя при этом ... github.com/WebApiContrib/WebApiContrib.Formatting.Jsonp
Работал у меня. Мне нужно было добавить , используя System.Net.Http.Formatting;
Связывание для моего удобства: этот ответ прекрасно сочетается с другим шагом настройки, который я обычно выполняю: coderhelper.com/a/28337589/398630.
И чтобы было ясно, это просто меняет значение по умолчанию. Вы всегда можете получить JSON или XML, просто включив соответствующий заголовок «Принять».
Он отлично работает с JSON, но не возвращает правильно отформатированный XML.
Это отлично работает с новейшими версиями браузеров при использовании .NET Framework.
Работает отлично ! Вы можете добавить приведенный ниже код, чтобы вернуть JSON с отступом: var jsonFormat = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); jsonFormat.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
(необходимо добавить using System.Net.Http.Formatting; using Newtonsoft.Json.Serialization;)
Мне больше всего нравится подход Фелипе Леусина - убедитесь, что браузеры получают JSON без ущерба для согласования содержимого со стороны клиентов, которым действительно нужен XML. Единственное, чего мне не хватало, это то, что заголовки ответов все еще содержали content-type: text / html. Почему это было проблемой? Потому что я использую расширение JSON Formatter Chrome, которое проверяет тип содержимого, и я не получаю того красивого форматирования, к которому я привык. Я исправил это с помощью простого настраиваемого средства форматирования, которое принимает запросы text / html и возвращает ответы application / json:
public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
public BrowserJsonFormatter() {
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
this.SerializerSettings.Formatting = Formatting.Indented;
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) {
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
Зарегистрируйтесь так:
config.Formatters.Add(new BrowserJsonFormatter());
В конструкторе добавьте this.SerializerSettings.Formatting = Formatting.Indented;
, если хотите, чтобы он выглядел красиво без расширения браузера.
Идеально. У меня были проблемы с решением Фелипе, возвращающим Content-Type text/html
, и это исправило его (и сделало ответ правильным!) Я объединил ваш ответ с ответом suhair, чтобы я получил JSON, отправленный в браузер по умолчанию, но у меня есть возможность добавления в строку запроса "format = xml" или "format = json" для выбора определенного средства форматирования. Спасибо!
почему вы хотите, чтобы он красиво печатал по проводам?
@meffect pretty-printing предпочтительнее при просмотре в браузере. Клиенты, запрашивающие json через application / json, все равно будут возвращать json без отступа.
Разве ответ @ dmit77 не лучше (более краткий), чем этот?
@AlastairMaw хорошая идея, добавил ваше предложение, поэтому красивая печать работает без расширения для браузера.
@eddiegroves, ты не хочешь красиво печатать по проводам. Вы хотите, чтобы сервер отправлял по сети наименьшее количество бит (т.е. без пробелов). Затем вы хотите, чтобы браузер красиво его отформатировал, добавив надстройки и тому подобное. Javascript обычно должен анализировать JSON, зачем делать его медленнее, вводя ненужное форматирование
Спасибо, Тодд, лучший ответ: 1) правильный тип возврата, 2) сохраняет красивое форматирование ТОЛЬКО из браузера И 3) мне не нужно добавлять новый тип подтверждения в Firefox, и Chrome также работает! Сладость.
Для тех, кто ищет: не забудьте добавить using System.Net.Http.Formatting
и using Newtonsoft.Json
Чтобы убедиться, что международные символы возвращаются правильно, установите правильную кодировку, добавив строку headers.ContentType.CharSet = "utf-8";
в конец функции SetDefaultContentHeaders()
.
Решение не работает с IE (например, все еще просит загрузить файл json). Что-нибудь исправить?
Поскольку вопрос относится к Chrome, вы можете получить расширение Postman, которое позволяет вам установить тип содержимого запроса.
В Firefox просто перейдите в about: config, найдите accept.default и измените содержимое конфигурации network.http.accept.default
на text/html,application/xhtml+xml,application/json;q=0.9,application/xml;q=0.8,*/*;q=0.7
.
Или еще лучше, просто text/html,application/xhtml+xml;q=1.0,*/*;q=0.7
, чтобы избежать случайного обслуживания ошибочными хостами, такими как Bitbucket, JSON вашего браузера вместо HTML.
URL мертв. Новый - chrome.google.com/webstore/detail/postman/….
Этот код делает json моим значением по умолчанию и позволяет мне также использовать формат XML. Я просто добавлю xml=true
.
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Спасибо всем!
Это наиболее гибкий ответ (и в наши дни он действительно должен быть конфигурацией по умолчанию). Чтобы добавить к этому ответу, по умолчанию используется JSON, в том числе из браузера. Для просмотра XML добавьте строку запроса:? Xml = true
Пробовал ряд стратегий. Был простой тест как для XML, так и для JSON, и это сработало из коробки
Я использовал глобальный фильтр действий, чтобы удалить Accept: application/xml
, когда заголовок User-Agent
содержит "Chrome":
internal class RemoveXmlForGoogleChromeFilter : IActionFilter
{
public bool AllowMultiple
{
get { return false; }
}
public async Task<HttpResponseMessage> ExecuteActionFilterAsync(
HttpActionContext actionContext,
CancellationToken cancellationToken,
Func<Task<HttpResponseMessage>> continuation)
{
var userAgent = actionContext.Request.Headers.UserAgent.ToString();
if (userAgent.Contains("Chrome"))
{
var acceptHeaders = actionContext.Request.Headers.Accept;
var header =
acceptHeaders.SingleOrDefault(
x => x.MediaType.Contains("application/xml"));
acceptHeaders.Remove(header);
}
return await continuation();
}
}
Кажется, работает.
В WebApiConfig.cs добавьте в конец функции Register :
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
XmlFormatter является новым в MVC4?
В MVC5 это можно сделать, заменив config на GlobalConfiguration.Configuration
Для проекта, который должен поддерживать только JSON и ни при каких обстоятельствах не может быть разрешено испускать XML, это, безусловно, лучший вариант.
config.Formatters.Add (config.Formatters.JsonFormatter);
Это ужасно. - Это всегда будет возвращать JSON независимо от того, что, даже если клиент специально запрашивает XML в заголовке Content-Type.
Проекты, которые не тестируют XML-версию API так тщательно, как их версия JSON, должны выбрать это. Объекты сериализуются по-разному разными программами форматирования согласно ссылке, которую указал Майкл. Например: средства форматирования XML не сериализуют поля, доступные только для чтения, в отличие от средства форматирования JSON.
Если вы сделаете это в WebApiConfig
, вы получите JSON по умолчанию, но он все равно позволит вам возвращать XML, если вы передадите text/xml
в качестве заголовка запроса Accept
.
Примечание: это удаляет поддержку для application/xml
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
}
}
Если вы не используете тип проекта MVC и, следовательно, у вас не было этого класса для начала, см. Этот ответ, чтобы узнать, как его включить.
Следует отметить, что исходное поведение правильное. Chrome запрашивает application/xml
с приоритетом 0,9 и */*
с приоритетом 0,8. Удаляя application/xml
, вы лишаете веб-API возможности возвращать XML, если клиент запрашивает именно это. например если вы отправите «Accept: application / xml», вы все равно получите JSON.
Основываясь на комментарии @ Porges, я предлагаю заключить две строки, удаляющие поддержку XML, в директиву #if DEBUG. Таким образом, в dev вы можете использовать адресную строку Chrome для тестирования вашего api и получения json по умолчанию, и вы по-прежнему будете предлагать поддержку XML в своей среде prod.
Это я, или первое предложение неверно? Код, похоже, полностью удаляет XML, а не просто меняет значение по умолчанию.
@NickG: да и нет, он удаляет поддержку application / xml, но вы все равно можете использовать text / xml. (Хотя text / xml считается устаревшим)
@NickG: решение, которое здесь упускается из виду, и IMHO - гораздо лучший вариант (сохранение application / xml) - это решение, предложенное Фелипе Леусином ниже на этой странице. Использование config.Formatters.XmlFormatter.SupportedMediaTypes.Add (new MediaTypeHeaderValue ("text / html"));
Итак, как нам сделать это через веб-конфигурацию, чтобы мы получали json по умолчанию и XML по запросу?
Ответ @Felipse Leusin ниже на самом деле короче и работает лучше.
Не используйте браузер для тестирования API.
Вместо этого попробуйте использовать HTTP-клиент, который позволяет указать ваш запрос, например CURL или даже Fiddler.
Проблема с этой проблемой в клиенте, а не в API. Веб-API работает правильно в соответствии с запросом браузера.
Почему бы не использовать браузер? Это очевидный инструмент для этого.
Я думаю, что здесь правильный и важный момент - мы не должны переопределять рабочую часть приложения (инфраструктуру MVC WebAPI), если проблема вызвана клиентом. Реальный вариант использования Api - это правильное использование (путем предоставления правильных заголовков), за что отвечает приложение. Я не согласен с тем, чтобы полностью отказаться от браузера - для тестирования есть множество инструментов практически для любого браузера (для начала, расширения, подобные Rest Client).
Вероятно, это должен быть комментарий.
В Global.asax я использую приведенный ниже код. Мой URI для получения JSON: http://www.digantakumar.com/api/values?json=true
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("json", "true", "application/json"));
}
Великий. Какой ваш метод ожидает параметр? например localhost: 61044 / api / values / getdate? json = true, date = 2012-08-01
Быстрый совет №3 по MVC4 - удаление средства форматирования XML из веб-API ASP.Net
В Global.asax
добавьте строку:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
вот так:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
Работает - гораздо приятнее использовать JSON по умолчанию вместо XML.
но можно ли тогда вернуть xml?
Я проверил это, и вы не можете. Таким образом, это удаляет поддержку XML. Будьте осторожны, уважаемые гуглеры.
Если вы посмотрите на мой ответ ниже, это позволит вернуть xml, если вы хотите, но позволит сайту отвечать JSON в браузере.
@GlennSlaven, да, ваш ответ должен быть помечен как правильный.
Добавление только последней строки GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
сработало для меня. Я получал ошибку во всех остальных строках. Это Web Form Apllication
Мне показалось, что приложение Chrome «Advanced REST Client» отлично подходит для работы со службами REST. Среди прочего вы можете установить Content-Type на application/json
:
Расширенный клиент REST
Один из быстрых вариантов - использовать специализацию MediaTypeMapping. Вот пример использования QueryStringMapping в событии Application_Start:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
Теперь всякий раз, когда URL-адрес содержит строку запроса? A = b, в этом случае в браузере будет отображаться ответ Json.
Это было очень полезно. Вы также можете использовать UriPathExtensionMapping вместо QueryStringMapping, если хотите использовать path.to/item.json
Посмотрите на согласование содержимого в WebAPI. Эти (Часть 1 & Часть 2) чудесно подробные и подробные сообщения в блоге объясняют, как это работает.
Короче говоря, вы правы, вам просто нужно установить заголовки запроса Accept
или Content-Type
. Если ваше действие не закодировано для возврата определенного формата, вы можете установить Accept: application/json
.
"чтобы я мог просмотреть его в браузере"
@Spongman, да, ты можешь. Но используйте такое расширение, как REST Client - оно есть в большинстве браузеров. Прямой ввод URL-адреса в браузере - 1. Слишком ограничен (нет контроля над заголовками, нельзя публиковать данные и т. Д.); 2. Неправильно - браузер не использует веб-API, поскольку он предназначен для использования - вы не можете полагаться на его правильное тестирование. Итак, опять же, хорошая надстройка клиента REST исправит это.
Здесь обсуждается, как сделать возврат JSON только поведением по умолчанию: github.com/aspnet/Mvc/issues/1765