Web API 2 возвращает текст / простые ответы

#c# #asp.net-mvc #json #asp.net-web-api2

#c# #asp.net-mvc #json #asp.net-web-api2

Вопрос:

Я действительно борюсь с чем-то, с чем, я надеюсь, люди здесь могут помочь. Я пишу RESTful API в Web API 2. Всякий раз, когда я отправляю запрос в эту службу, ответ последовательно отправляется с Content-Type помощью of text/plain . Очевидно, что это никуда не годится, мой ответ должен быть Content-Type application/json . Я попробовал несколько предложений, которые я нашел в Google, но я не думаю, что понимаю всю картину.

Есть ли что-то особенное, что мне нужно сделать, чтобы мой веб-сервис отвечал application/json контентом? Обратите внимание, что я хочу, чтобы это работало глобально во всем приложении, поэтому я не ищу способ изменить данный ответ и установить его тип содержимого — я хочу, чтобы это было поведение по умолчанию для всей веб-службы: если запрос содержит Accept заголовок для application/json , я хочу, чтобы мой веб-сервис возвращал этовместо Content-Type text/plain .

Отредактируйте, чтобы уточнить:

Мой ответ содержит объект с именем «responseData», который должен быть сериализован в JSON и включен в тело. В настоящее время я собираю свой ответ следующим образом:

 HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, responseData);
return response;
  

responseData это POCO. Этот get правильно сериализуется как JSON и возвращается в ответе — единственной недостающей частью является тип содержимого, для которого неверно задано значение «текст / обычный». Я мог бы вручную изменить это для каждого отдельного ответа, который я составляю, но я хочу настроить это на глобальном уровне.

Комментарии:

1. Возвращает ли рассматриваемый API a string с содержимым JSON, которое вы создали самостоятельно?

2.Проверьте это asp.net/web-api/overview/formats-and-model-binding/… ,msdn.microsoft.com/en-us/magazine/dn574797.aspx ,http://…,

3. @Corey в настоящее время ответ создается следующим образом: HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, responseData); а затем я просто возвращаюсь response в свое действие. Содержимое responseData хорошо сериализуется в JSON, но фактический заголовок content-type по-прежнему имеет значение text / plain : (

4. @malkam похоже, что этот пост касается кодировок, меня интересуют типы контента

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

Ответ №1:

Хорошо, предполагая, что ваш responseData является строкой, Content-type заголовок будет text/plain при создании HttpResponseMessage . Не имеет значения, каково содержимое строки, поскольку не предпринимается никаких попыток определить это.

Решение состоит в том, чтобы создать соответствующий объект содержимого для вашего сообщения, инициализированный типом возвращаемого носителя:

 HttpResponseMessage response = new HttpResponseMessage()
    {
        Content = new StringContent(
                responseData,
                Encoding.UTF8,
                "application/json"
            )
    };
  

Существуют и другие методы, которые сводятся к возврату определенного типа объекта и позволяют библиотекам API сериализоваться в JSON или XML для вас по мере необходимости. Я предпочитаю, чтобы фреймворк выполнял всю работу за меня, где это возможно, но именно так вы могли бы добиться этого с помощью строки, которую создали сами.


Для получения строгого результата только для JSON удалите средство форматирования XML из конфигурации WebAPI и верните свой POCO.

В App_StartWebApiConfig.cs , добавьте следующее к WebApiConfig.Register методу:

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

И для вашего API:

 public class MyObject
{
    public bool resu<
    public string reason;
}

public class TestController : ApiController
{
    public MyObject GetData()
    {
        MyObject result = new MyObject { result = "true", reason = "Testing POCO return" };
        return resu<
    }
}
  

Я запустил это и запросил /api/Test у Chrome, который даже не упоминается application/json в Accept заголовке. Вот заголовки ответа до тех пор, пока он не попадет Content-Type :

 HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
  

И тело:

 {"result":true,"reason":"Testing POCO return"}
  

Поскольку я отключил XML, по умолчанию используется JSON.

Комментарии:

1. Как упоминалось в моем вопросе, я пытаюсь найти глобальный способ настроить это, вместо того, чтобы явно определять тип контента для каждого создаваемого мной ответа. Возможно, моя формулировка была немного неясной — я отредактировал свой OP, чтобы, надеюсь, прояснить пару моментов.

2. Вы пробовали просто возвращать сам объект? HttpResponseMessage это нормально, когда вы хотите больше контролировать отдельные возвраты, но вы можете вернуть POCO и позволить библиотекам позаботиться о сериализации за вас — JSON или XML, в зависимости от Accept заголовка в запросе.

3. Я полагаю, проблема в том, что мне все равно придется возвращать 404 или 500 и т. Д., Если что-то пойдет не так — возможно ли это при использовании описанного подхода?

4. Да, путем HttpResponseException ввода .

Ответ №2:

Добавьте следующее в глобальный файл.asax.

 protected void Application_Start()
{

JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new IsoDateTimeConverter());
var jsonFormatter = new JsonNetFormatter(serializerSettings);
jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
GlobalConfiguration.Configuration.Formatters.Insert(0, jsonFormatter);

}
  

Комментарии:

1. Это предполагает, что кто-то создал какой-то jsonnet Formatter и не работает без этого понимания или более подробной информации.

Ответ №3:

Другой возможный источник описанной проблемы заключается в том, что в игре может быть перенаправление авторизации, как это было в нашем случае, когда один из инженеров решил повторно использовать аутентификацию пользователя для api.

Это означает, что входящие запросы перенаправлялись на страницу входа в систему, которая была text/html ответом, который не мог быть проанализирован ReadAsync<> . Конечно, глупая ошибка, но ее нелегко обнаружить.

Решением в этом случае было удалить аутентификацию пользователя и реализовать аутентификацию на основе HMAC для api.