Помістити вміст у об’єкт 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()якщо відповідь є помилкою, як це є в прикладі цієї відповіді. Всередині мого спробу лову я використовую: 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
що таке мійFormatter
Greg Z.

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

1
ObjectContentне знайдено, використовуючи WCF
Medet Tleukabiluly

2
Я б не кваліфікував це як "новий спосіб зробити це" - ця стаття, яку ви посилаєте, перераховує це як альтернативу у випадку, якщо ви хочете мати "повний контроль над форматом [тип медіа], який ви хочете використовувати"
Берн

Дякую @praetor Це мені дуже допомогло
SO Користувач

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.