Bagaimana cara mendapatkan isi konten dari panggilan httpclient?

108

Saya telah mencoba mencari cara untuk membaca konten panggilan httpclient, dan sepertinya saya tidak bisa mendapatkannya. Status respons yang saya dapat adalah 200, tetapi saya tidak tahu bagaimana caranya agar Json yang sebenarnya dikembalikan, yang saya butuhkan!

Berikut ini adalah kode saya:

async Task<string> GetResponseString(string text)
{
    var httpClient = new HttpClient();

    var parameters = new Dictionary<string, string>();
    parameters["text"] = text;
    Task<HttpResponseMessage> response = 
        httpClient.PostAsync(BaseUri, new FormUrlEncodedContent(parameters));

    return await response.Result.Content.ReadAsStringAsync();
}

Dan saya mendapatkannya hanya dengan memanggilnya dari sebuah metode:

Task<string> result =  GetResponseString(text);

Dan inilah yang saya dapatkan

response Id = 89, Status = RanToCompletion, Method = "{null}", Result = "StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:\r\n{\r\n Connection: keep-alive\r\n Date: Mon, 27 Oct 2014 21:56:43 GMT\r\n ETag: \"5a266b16b9dccea99d3e76bf8c1253e0\"\r\n Server: nginx/0.7.65\r\n Content-Length: 125\r\n Content-Type: application/json\r\n}" System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>

Pembaruan: Ini adalah kode saya saat ini sesuai dengan tanggapan Nathan di bawah ini

    async Task<string> GetResponseString(string text)
    {
        var httpClient = new HttpClient();

        var parameters = new Dictionary<string, string>();
        parameters["text"] = text;

        var response = await httpClient.PostAsync(BaseUri, new FormUrlEncodedContent(parameters));
        var contents = await response.Content.ReadAsStringAsync();

        return contents;
    }

Dan saya menyebutnya dari metode ini ....

 string AnalyzeSingle(string text)
    {
        try
        {
            Task<string> result = GetResponseString(text);
            var model = JsonConvert.DeserializeObject<SentimentJsonModel>(result.Result);

            if (Convert.ToInt16(model.pos) == 1)
            {
                _numRetries = 0;
                return "positive";
            }

            if (Convert.ToInt16(model.neg) == 1)
            {
                _numRetries = 0;
                return "negative";
            }

            if (Convert.ToInt16(model.mid) == 1)
            {
                _numRetries = 0;
                return "neutral";
            }

            return "";
        }
        catch (Exception e)
        {
            if (_numRetries > 3)
            {
                LogThis(string.Format("Exception caught [{0}] .... skipping", e.Message));
                _numRetries = 0;
                return "";
            }
            _numRetries++;
            return AnalyzeSingle(text);
        }
    }

Dan terus berjalan selamanya, Ini menyentuh garis var model = JsonConvert.DeserializeObject<SentimentJsonModel>(result.Result); Sekali, dan terus berjalan tanpa berhenti di breakpoint lain.

Saat saya menghentikan eksekusi, Ia berkata

Id = Tidak dapat mengevaluasi ekspresi karena kode metode saat ini dioptimalkan., Status = Tidak dapat mengevaluasi ekspresi karena kode metode saat ini dioptimalkan., Metode = Tidak dapat mengevaluasi ekspresi karena kode dari metode saat ini dioptimalkan., Hasil = Tidak dapat mengevaluasi ekspresi karena kode metode saat ini dioptimalkan.

.. Saya melanjutkan eksekusi, tapi itu berjalan selamanya. Tidak yakin apa masalahnya

Sherman Szeto
sumber
Di mana dan bagaimana _numRetries didefinisikan?
Nathan A
Ini dalam ruang lingkup kelas dan diinisialisasi dengan 0 di konstruktor. AnalyzeSingle () adalah satu-satunya tempat saya menggunakannya.
Sherman Szeto
Apakah Anda menjalankan mode Debug? Masalah yang dioptimalkan mungkin karena Anda menjalankan mode Rilis.
Nathan A
Saat ini saya menggunakan Debug / iisExpress
Sherman Szeto

Jawaban:

176

Cara Anda menggunakan await / async paling buruk, dan membuatnya sulit untuk diikuti. Anda bercampur awaitdengan Task'1.Result, yang hanya membingungkan. Namun, sepertinya Anda melihat hasil tugas akhir, bukan isinya.

Saya telah menulis ulang pemanggilan fungsi dan fungsi Anda, yang seharusnya memperbaiki masalah Anda:

async Task<string> GetResponseString(string text)
{
    var httpClient = new HttpClient();

    var parameters = new Dictionary<string, string>();
    parameters["text"] = text;

    var response = await httpClient.PostAsync(BaseUri, new FormUrlEncodedContent(parameters));
    var contents = await response.Content.ReadAsStringAsync();

    return contents;
}

Dan panggilan fungsi terakhir Anda:

Task<string> result = GetResponseString(text);
var finalResult = result.Result;

Atau bahkan lebih baik:

var finalResult = await GetResponseString(text);
Nathan A
sumber
Terima kasih!! Saya telah mencoba untuk mendapatkan cara kerja async / await selama beberapa jam terakhir (MSDN + stackoverflow), tetapi saya jelas belum memahami sepenuhnya. Apakah ada sumber daya yang Anda sarankan?
Sherman Szeto
1
Teruslah bermain-main dengannya dan Anda akan terbiasa pada akhirnya. Ini adalah konsep besar untuk dipahami sekaligus.
Nathan A
Saya masih mengalami masalah. Saya memperbarui masalah saya di postingan asli. Masalahnya mungkin saya membuat kode untuk eksekusi sinkron, tetapi saya tidak yakin bagaimana menyelesaikan masalah itu
Sherman Szeto
1
HttpClient mengimplementasikan IDisposable, jadi lebih baik membungkusnya dalam pernyataan using.
Payam
2
@Payam meskipun benar bahwa itu mengimplementasikan, IDisposableAnda tidak boleh membungkusnya dalam sebuah usingpernyataan. Ini pengecualian langka untuk aturan tersebut. Lihat posting ini untuk informasi lebih lanjut: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty
62

Jika Anda tidak ingin menggunakan, asyncAnda dapat menambahkan .Resultuntuk memaksa kode dijalankan secara sinkron:

private string GetResponseString(string text)
{
    var httpClient = new HttpClient();

    var parameters = new Dictionary<string, string>();
    parameters["text"] = text;

    var response = httpClient.PostAsync(BaseUri, new FormUrlEncodedContent(parameters)).Result;
    var contents = response.Content.ReadAsStringAsync().Result;

    return contents;
 }  
nbushnell
sumber
2
@nbushnell menambahkan. Hasil ke PostAsync Anda menjadikannya non-asinkron
Mike
6
@ Mike bukankah itu yang dikatakan nbushnell? :-)
PoeHaH
Untuk apa tipe ini response? Saya memiliki kode serupa tetapi saya perlu membuatnya responseglobal, jadi saya membutuhkan tipenya. Terima kasih.
Azurespot
1
@AzureSpot: De jenis tanggapannya adalah HttpResponseMessage.
RWC