Как заставить ASP.NET Web API возвращать JSON вместо XML с помощью Chrome?

Используя новый ASP.NET Web API, в Chrome, я вижу XML - как я могу его изменить, чтобы запросить JSON, чтобы я можете просмотреть его в браузере? Я действительно верю, что это всего лишь часть заголовков запросов, я прав в этом?

Ответы

Ответ 1

Я просто добавляю следующее в класс App_Start / WebApiConfig.cs в проект MVC Web API.

config.Formatters.JsonFormatter.SupportedMediaTypes
    .Add(new MediaTypeHeaderValue("text/html") );

Это гарантирует, что вы получите json для большинства запросов, но вы можете получить xml при отправке text/xml.

Если вам нужен ответ Content-Type как application/json, пожалуйста, проверьте ответ Todd ниже.

NameSpace использует System.Net.Http.Headers;

Ответ 2

Если вы сделаете это в WebApiConfig, вы получите JSON по умолчанию, но он все равно позволит вам вернуть XML, если вы передадите text/xml в качестве заголовка запроса Accept

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 и, следовательно, не имели этого класса для начала, см. этот ответ для получения подробной информации о том, как его включить.

Ответ 3

Мне нравится подход Felipe Leusin - убедитесь, что браузеры получают JSON без компрометации согласования контента с клиентами, которые действительно хотят XML. Единственным недостающим моментом для меня было то, что заголовки ответов по-прежнему содержали контент-тип: text/html. Почему это проблема? Потому что я использую расширение

Зарегистрируйся так:

config.Formatters.Add(new BrowserJsonFormatter());

Ответ 4

Использование 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"));

Ответ 5

MVC4 Quick Tip # 3-Извлечение XML Formatter из веб-интерфейса 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();
}

Ответ 6

В WebApiConfig.cs добавьте в конец функции Регистрация:

// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);

Источник.

Ответ 7

В 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"));
}

Ответ 8

Посмотрите на согласование контента в WebAPI. Эти (Часть 1 и Часть 2) чудесно подробные и подробные сообщения в блогах объясняют, как это работает.

Короче говоря, вы правы, и вам просто нужно установить заголовки запросов Accept или Content-Type. Если ваше действие не закодировано для возврата определенного формата, вы можете установить Accept: application/json.

Ответ 9

Поскольку вопрос специфичен для Chrome, вы можете получить расширение Postman, которое позволяет вам установить тип содержимого запроса.

Postman

Ответ 10

Одним быстрым вариантом является использование специализации MediaTypeMapping. Ниже приведен пример использования QueryStringMapping в событии Application_Start:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));

Теперь, когда URL-адрес содержит запрос, a = b, в браузере будет отображаться ответ Json.

Ответ 11

Этот код делает 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"));

Спасибо всем!

Ответ 12

Не используйте браузер для тестирования вашего API.

Вместо этого попробуйте использовать HTTP-клиент, который позволяет вам указать ваш запрос, такой как CURL или даже Fiddler.

Проблема с этой проблемой возникает в клиенте, а не в API. Веб-API ведет себя правильно, в соответствии с запросом браузера.

Ответ 13

Я использовал глобальный фильтр действий для удаления 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();
    }
}

Кажется, работает.

Ответ 14

Большая часть приведенных выше ответов имеет смысл. Поскольку вы видите, что данные отформатированы в формате XML, это означает, что применяется формат XML, SO, вы можете видеть формат 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 является стандартным форматом

Ответ 15

Я обнаружил, что приложение Chrome "Advanced REST Client" отлично работает с службами REST. Вы можете установить Content-Type на application/json между прочим: Расширенный клиент REST

Ответ 16

Вот решение, подобное 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 при тестировании с помощью браузера. Это не мешает другим ожидаемым действиям при использовании не-браузерного клиента, где вы можете установить свои собственные заголовки.

Ответ 17

Мне непонятно, почему в этом есть вся эта сложность. Конечно, есть много способов сделать это, с 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 или, возможно, созданы где-то в другом месте (кем-то другим в моем проекте). Anways, надеюсь, что это поможет.

Ответ 18

Вы просто измените 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}"
       );
    }

Ответ 19

в соответствии с последней версией ASP.net WebApi 2,

под WebApiConfig.cs, это будет работать

config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);

Ответ 20

Прошло некоторое время с момента запроса (и ответа), но другой вариант - переопределить заголовок 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;
    }
}

Ответ 21

Вот самый простой способ, который я использовал в своих приложениях. Добавьте приведенные ниже 3 строки кода в App_Start\\WebApiConfig.cs в Register функцию

    var formatters = GlobalConfiguration.Configuration.Formatters;

    formatters.Remove(formatters.XmlFormatter);

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));

Web-API Asp.net автоматически преобразует ваш возвращаемый объект в JSON и добавит application/json в заголовок, чтобы браузер или получатель понимали, что вы возвращаете результат JSON.

Ответ 22

Просто добавьте эти две строки кода в класс WebApiConfig

public static class WebApiConfig
{
     public static void Register(HttpConfiguration config)
     {
          //add this two line 
          config.Formatters.Clear();
          config.Formatters.Add(new JsonMediaTypeFormatter());


          ............................
      }
}

Ответ 23

Возврат правильного формата выполняется форматом медиа-типа. Как уже упоминалось, вы можете сделать это в классе 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"));

        ...
    }
}

Для получения дополнительной информации проверьте:

В случае, если ваши действия возвращают 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].

Ответ 24

        config.Formatters.Remove(config.Formatters.XmlFormatter);

Ответ 25

От 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();
    }

Он должен быть текущим, я попробовал его, и он сработал.

Ответ 26

WebApiConfig - это место, где вы можете настроить, хотите ли вы выводить в json или xml. по умолчанию это xml. в функции register мы можем использовать HttpConfiguration Formatters для форматирования вывода. System.Net.Http.Headers = > MediaTypeHeaderValue ( "text/html" ) требуется получить выход в формате json. введите описание изображения здесь

Ответ 27

Самый простой способ:

 GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

Ответ 28

Добавление $format = json в конец MVC4 + webapi-функции теперь возвращает результат как json, а $format = xml возвращает XML. Это нормально в Chrome, поскольку он отображает данные JSON на экране, но в IE вам будет предложено загрузить результирующие данные json.