Поместить содержимое в объект HttpResponseMessage?


180

Несколько месяцев назад Microsoft решила изменить класс HttpResponseMessage. Раньше вы могли просто передать тип данных в конструктор, а затем вернуть сообщение с этими данными, но не больше.

Теперь вам нужно использовать свойство Content, чтобы установить содержимое сообщения. Проблема в том, что он имеет тип HttpContent, и я не могу найти способ конвертировать строку, например, в HttpContent.

Кто-нибудь знает, как бороться с этим вопросом? Большое спасибо.

Ответы:


216

Для конкретной строки самый быстрый способ - использовать конструктор StringContent.

response.Content = new StringContent("Your response text");

Существует ряд дополнительных потомков класса HttpContent для других распространенных сценариев.


См. Мой пост ниже для создания ваших собственных производных типов StringContent (например, JSON, XML и т. Д.).
bytedev

135

Вы должны создать ответ, используя Request.CreateResponse :

HttpResponseMessage response =  Request.CreateResponse(HttpStatusCode.BadRequest, "Error message");

Вы можете передавать объекты, а не только строки, CreateResponse, и он будет сериализовывать их на основе заголовка Accept запроса. Это избавит вас от ручного выбора форматера.


Он автоматически работает с типами контента, поэтому вы можете делать XML / JSON без дополнительного кода

Я думаю, что было бы правильнее позвонить, CreateErrorResponse()если ответ является ошибкой, как в примере с этим ответом. Внутри моего try-catch я использую: this.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "message", exception); И, это правильный ответ, если вас вообще беспокоит соблюдение заголовка Accept вызывающего, без лишних махинаций. (И вы используете WebAPI)
JMD

2
@FlorinDumitrescu Суть его заключалась в том, что это работает ТОЛЬКО для тех случаев, когда вы наследуете ApiController. Если вы Controllerвместо этого только наследуете , это не работает, и вы должны создать его самостоятельно: HttpResponseMessage msg = new HttpResponseMessage(); msg.Content = new StringContent("hi"); msg.StatusCode = HttpStatusCode.OK;
vapcguy

64

Видимо, новый способ сделать это подробно здесь:

http://aspnetwebstack.codeplex.com/discussions/350492

По словам Хенрика,

HttpResponseMessage response = new HttpResponseMessage();

response.Content = new ObjectContent<T>(T, myFormatter, "application/some-format");

Таким образом, в основном необходимо создать тип ObjectContent, который, очевидно, можно вернуть как объект HttpContent.


31
что такое myFormatter
Грег З.

1
@ user1760329 это будет new JsonMediaTypeFormatter();или похоже в зависимости от вашего формата
Джон

1
ObjectContentне найден, используя WCF
Медет Тлеукабилулы

2
Я бы не назвал это «новым способом сделать это» - эта статья, на которую вы ссылаетесь, перечисляет ее в качестве альтернативы, если вы хотите иметь «полный контроль над форматером [media-type], который вы хотите использовать»
Берн

Спасибо @praetor. Это было очень полезно для меня
SO User

53

Самым простым однострочным решением является использование

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( "Your message here" ) };

Для сериализованного контента JSON:

return new HttpResponseMessage( HttpStatusCode.OK ) {Content =  new StringContent( SerializedString, System.Text.Encoding.UTF8, "application/json" ) };

это не сработало для меня, потому что IHttpActionResult требует тип возврата ResponseMessageResult. Посмотрите мой ответ ниже для того, что я закончил. Также обратите внимание, что я учел фактор JsonContent для nashawn (полученный из базового класса StringContent).
Адам Кокс

1
Просто оберните HttpResponseMessage затем: верните новый ResponseMessageResult (верните новое HttpResponseMessage (HttpStatusCode.OK) {new StringContent («Ваше сообщение здесь»)}); :)
Саймон Маттес

41

Для любого объекта T вы можете сделать:

return Request.CreateResponse<T>(HttpStatusCode.OK, Tobject);

5
Исключение Requestдоступно только для CreateResponseметода, если вы наследуете ApiController. Это не будет работать при использовании Controller.
vapcguy

15

Вы можете создавать свои собственные специализированные типы контента. Например, один для содержимого Json и один для содержимого Xml (затем просто назначьте их для HttpResponseMessage.Content):

public class JsonContent : StringContent
{
    public JsonContent(string content)
        : this(content, Encoding.UTF8)
    {
    }

    public JsonContent(string content, Encoding encoding)
        : base(content, encoding, "application/json")
    {
    }
}

public class XmlContent : StringContent
{
    public XmlContent(string content) 
        : this(content, Encoding.UTF8)
    {
    }

    public XmlContent(string content, Encoding encoding)
        : base(content, encoding, "application/xml")
    {
    }
}

очень аккуратная и чистая реализация.
Сэм

3

Вдохновленный ответом Саймона Мэттеса, мне нужно было удовлетворить IHttpActionResult требуемый тип возврата ResponseMessageResult. Кроме того, используя JsonContent от Nashawn, я получил ...

        return new System.Web.Http.Results.ResponseMessageResult(
            new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.OK)
            {
                Content = new JsonContent(JsonConvert.SerializeObject(contact, Formatting.Indented))
            });

Смотрите ответ nashawn для JsonContent.


Интерполяция строк кажется ненужной
Игорь

0

Не сомневаюсь, что вы правы, Флорин. Я работал над этим проектом и обнаружил, что этот кусок кода:

product = await response.Content.ReadAsAsync<Product>();

Может быть заменено на:

response.Content = new StringContent(string product);

1
Этот ответ не имеет отношения к вопросу и не показывает, как перейти от объекта (продукта) к строке
mageos
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.