Поместить содержимое в объект 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.