only - web api return json error




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

MVC4 Quick Tip # 3 - Извлечение XML Formatter из ASP.Net Web API

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

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


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


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

В WebApiConfig.cs добавьте в конец функции Register :

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

Source .


Вот решение, подобное jayson.centeno's и другим ответам, но использующее встроенное расширение из 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 Content-Type: application/json; charset=utf-8 в ответе.

Это позволяет вам сжать &$format=json или &$format=xml до конца вашего uri при тестировании с помощью браузера. Это не мешает другим ожидаемым действиям при использовании не-браузерного клиента, где вы можете установить свои собственные заголовки.


Вот самый простой способ, который я использовал в своих приложениях. Добавьте приведенные ниже 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}"
       );
    }

Если вы сделаете это в 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 и, следовательно, не имели этого класса для начала, см. Этот ответ, чтобы узнать, как его включить.


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

Используя ответ Фелипе Леусина в течение многих лет, после недавнего обновления основных библиотек и Json.Net, я столкнулся с System.MissingMethodException : SupportedMediaTypes. Решение в моем случае, надеюсь, полезно другим, испытывающим такое же неожиданное исключение, - установить System.Net.Http . NuGet, по-видимому, удаляет его при некоторых обстоятельствах. После ручной установки проблема была решена.


Мне нравится подход Felipe Leusin - убедитесь, что браузеры получают JSON без компрометации согласования контента с клиентами, которые действительно хотят XML. Единственным недостающим моментом для меня было то, что заголовки ответов по-прежнему содержали контент-тип: text / html. Почему это проблема? Поскольку я использую расширение JSON Formatter Chrome , которое проверяет тип содержимого, и я не получаю красивое форматирование, к которому я привык. Я исправил это с помощью простого пользовательского форматирования, который принимает запросы text / html и возвращает ответы приложения / 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());

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

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

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


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


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

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


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

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

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


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


Я удивлен, увидев столько ответов, требующих кодирования, чтобы изменить один вариант использования (GET) в одном API вместо того, чтобы использовать надлежащий инструмент, который должен быть установлен один раз и может использоваться для любого API (собственного или третьего лица) и всех случаи применения.

Итак, хороший ответ:

  1. Если вы хотите только запросить json или другой тип контента, установите « Requestly или аналогичный инструмент и измените заголовок Accept.
  2. Если вы хотите использовать POST и умело форматировать json, xml и т. Д., Используйте подходящее расширение для тестирования API, такое как Postman или ARC .

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

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

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

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

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


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




asp.net-web-api