Pobieranie treści / wiadomości z HttpResponseMessage

175

Próbuję uzyskać zawartość HttpResponseMessage. Powinno być: {"message":"Action '' does not exist!","success":false}ale nie wiem, jak to wyciągnąć z HttpResponseMessage.

HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync("http://****?action=");
txtBlock.Text = Convert.ToString(response); //wrong!

W tym przypadku txtBlock miałby wartość:

StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Vary: Accept-Encoding
  Keep-Alive: timeout=15, max=100
  Connection: Keep-Alive
  Date: Wed, 10 Apr 2013 20:46:37 GMT
  Server: Apache/2.2.16
  Server: (Debian)
  X-Powered-By: PHP/5.3.3-7+squeeze14
  Content-Length: 55
  Content-Type: text/html
}
Clem
źródło

Odpowiedzi:

66

Musisz wywołać GetResponse () .

Stream receiveStream = response.GetResponseStream ();
StreamReader readStream = new StreamReader (receiveStream, Encoding.UTF8);
txtBlock.Text = readStream.ReadToEnd();
Lodziarz
źródło
33
Dzięki, ale dlaczego widzę ten błąd tutaj: „System.Net.Http.HttpResponseMessage” nie zawiera definicji „GetResponseStream” ani metody rozszerzenia „GetResponseStream” akceptującej pierwszy argument typu „System.Net.Http.HttpResponseMessage” można znaleźć ”
Clem,
13
@Klemzy - ponieważ nazywasz to asynchronicznie. ContentZamiast tego spróbuj użyć właściwości. Spójrz na przykład tutaj . Przewiń w dół do drugiego kroku.
Icemanind
2
@Klemzy - Spójrz na przykład tutaj . Przewiń w dół do drugiego kroku. Jeśli nie możesz tego
rozgryźć, edytuję
17
Ta odpowiedź jest całkowicie nie na temat, OP używa HttpClient, a nie HttpWebRequest/ HttpWebResponse.
Maxime Rossini
1
Pytanie dotyczy HttpCient, Twoja odpowiedź jest oparta na przestarzałym i przestarzałym HttpWebRequest.
Payam
370

Myślę, że najłatwiejszym sposobem jest zmiana ostatniej linii na

txtBlock.Text = await response.Content.ReadAsStringAsync(); //right!

W ten sposób nie musisz wprowadzać żadnych czytników strumieniowych i nie potrzebujesz żadnych metod rozszerzających.

rudivonstaden
źródło
5
Nie jestem pewien, dlaczego nie jest to akceptowana odpowiedź, zwłaszcza, że ​​daje to możliwość łatwej serializacji zawartości do obiektów.
Jason McKindly
3
ReadAsStringAsync nie obsługuje dobrze błędów IMHO.
stannius
16
Możesz również użyć Response.Content.ReadAsStringAsync (). Wynik zamiast użycia await
Justin
8
Uważaj jednak: ReadAsStringAsync () może generować, jeśli w odpowiedzi masz emotikony lub inne znaki Unicode. Musiałem użyć strumieni (jak w przyjętej odpowiedzi), aby to przezwyciężyć.
Ginkgo
41

Spróbuj tego, możesz utworzyć taką metodę rozszerzenia:

    public static string ContentToString(this HttpContent httpContent)
    {
        var readAsStringAsync = httpContent.ReadAsStringAsync();
        return readAsStringAsync.Result;
    }

a następnie po prostu wywołaj metodę rozszerzenia:

txtBlock.Text = response.Content.ContentToString();

Mam nadzieję, że to pomoże ;-)

MCurbelo
źródło
Zdecydowanie najłatwiejsze do uruchomienia
Aage
Użyj awaitzamiast .Result... lub zamiast tego użyj synchronicznego klienta HTTP, jeśli Twój kod nie obsługuje programowania asynchronicznego. Ale każdy nowoczesny kod powinien, w przeciwnym razie może to oznaczać, że Twoja aplikacja robi coś źle.
Maxime Rossini
9

Jeśli chcesz rzutować go na określony typ (np. W ramach testów) możesz użyć metody rozszerzenia ReadAsAsync :

object yourTypeInstance = await response.Content.ReadAsAsync(typeof(YourType));

lub następujące dla kodu synchronicznego:

object yourTypeInstance = response.Content.ReadAsAsync(typeof(YourType)).Result;

Aktualizacja: istnieje również ogólna opcja ReadAsAsync <>, która zwraca określone wystąpienie typu zamiast zadeklarowanego przez obiekt:

YourType yourTypeInstance = await response.Content.ReadAsAsync<YourType>();
taras-mytofir
źródło
2
obiekt yourTypeInstance = await response.Content.ReadAsAsync (typeof (YourType)); powinno być var ​​yourTypeInstance = await response.Content.ReadAsAsync <YourType> ();
Thomas.Benz
Użyłem Request.Content.ReadAsAsync do przeanalizowania Json i uzyskałem okropną wydajność.
W.Leto,
4

Odpowiedzią rudivonstaden

`txtBlock.Text = await response.Content.ReadAsStringAsync();`

ale jeśli nie chcesz, aby metoda była asynchroniczna, możesz użyć

`txtBlock.Text = response.Content.ReadAsStringAsync();
 txtBlock.Text.Wait();`

Wait () jest to ważne, ponieważ wykonujemy operacje asynchroniczne i musimy poczekać na zakończenie zadania przed kontynuowaniem.

stanimirsp
źródło
3
używając .Resultinnego ?,httpContent.ReadAsStringAsync().Result
mkb
.Resultzablokowałoby wykonanie wątku w tej linii ... gdzie jako txtBlock.Text.Wait()bloki wywołania wait () ... więc masz rację, że w zasadzie nie ma różnicy. Ale podejrzewam txtBlock.Text.Wait(), że przyjąłby opcjonalny parametr całkowity, więc GUI nie zawiesza się, jeśli poprzednie ReadAsStringAsync()wywołanie nigdy nie powróci. Na przykład następująca blokada nie txtBlock.Text.Wait(1000)
potrwa
3

Szybka odpowiedź, którą sugeruję, to:

response.Result.Content.ReadAsStringAsync().Result

benhorgen
źródło
NIE wzywaj Resultzadań. Ryzykujesz zablokowanie aplikacji. Zamiast tego użyj async / await.
eltiare
Nie powiedziałbym nigdy ... czasami robi się to szybko i brudno. Ale zgadzam się, że ryzykujesz, że ReadAsStringAsync()nie powrócisz, więc upewnij się, że nie wywołujesz tego w swoim GUI lub głównym wątku aplikacji.
benhorgen
1

Myślę, że poniższy obraz pomaga tym, którzy muszą przyjść Tjako typ zwrotu.

wprowadź opis obrazu tutaj

snr
źródło
0

Możesz użyć GetStringAsyncmetody:

var uri = new Uri("http://yoururlhere");
var response = await client.GetStringAsync(uri);
Hinrich
źródło