Помістити вміст у об’єкт 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.