Bir httpclient çağrısından içerik gövdesi nasıl alınır?


111

Bir httpclient çağrısının içeriğini nasıl okuyacağımı bulmaya çalışıyorum ve anlayamıyorum. Aldığım yanıt durumu 200, ancak iade edilen gerçek Json'a nasıl ulaşacağımı çözemiyorum, tek ihtiyacım olan bu!

Aşağıdaki kodum:

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();
}

Ve bunu bir yöntemden çağırdığımı anlıyorum:

Task<string> result =  GetResponseString(text);

Ve bu elde ettiğim şey

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>

Güncelleme: Bu, Nathan'ın aşağıdaki yanıtı başına mevcut kodum

    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;
    }

Ve ben buna bu yöntemden diyorum ...

 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);
        }
    }

Ve sonsuza kadar koşmaya var model = JsonConvert.DeserializeObject<SentimentJsonModel>(result.Result); devam ediyor, Bir Kez çizgisine ulaşıyor ve başka bir kırılma noktasında durmadan gitmeye devam ediyor.

Yürütmeyi duraklattığımda diyor ki

Id = Mevcut yöntemin kodu optimize edildiği için ifade değerlendirilemiyor., Durum = Mevcut yöntemin kodu optimize edildiğinden ifade değerlendirilemiyor., Yöntem = Mevcut yöntemin kodu optimize edildiği için ifade değerlendirilemiyor., Sonuç = Geçerli yöntemin kodu optimize edildiği için ifade değerlendirilemiyor.

.. Yürütmeye devam ediyorum, ancak sonsuza kadar devam ediyor. Sorunun ne olduğundan emin değilim


_NumRetries nerede ve nasıl tanımlanır?
Nathan A

Sınıfın kapsamındadır ve yapıcıda 0 ile başlatılır. AnalyzeSingle () onu kullandığım tek yer.
Sherman Szeto

Hata Ayıklama modunda mı çalışıyorsunuz? Optimize edilmiş sorun, Yayın modunda çalıştığınız için olabilir.
Nathan A

Şu anda Debug / iisExpress'teyim
Sherman Szeto

Yanıtlar:


178

Await / async kullanma şekliniz en iyi ihtimalle zayıftır ve takip edilmesini zorlaştırır. Sen karıştırma awaitile Task'1.Resultsadece kafa karıştırıcı olan. Ancak, içerikten ziyade nihai bir görev sonucuna bakıyorsunuz gibi görünüyor.

Sorununuzu çözmesi gereken işlev ve işlev çağrınızı yeniden yazdım:

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;
}

Ve son işlev çağrınız:

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

Ya da daha iyisi:

var finalResult = await GetResponseString(text);

Teşekkürler!! Son birkaç saattir async / await'in nasıl çalıştığını anlamaya çalışıyorum (MSDN + stackoverflow), ancak açıkçası henüz tam olarak kavrayamadım. Önerebileceğiniz kaynaklar var mı?
Sherman Szeto

1
Sadece onunla oynamaya devam edin ve sonunda asılacaksınız. Hepsini aynı anda kavramak büyük bir kavramdır.
Nathan A

Hâlâ sorunlar yaşıyorum. Sorunumu orijinal gönderide güncelledim. Sorun, eşzamanlı çalıştırma için kod yazıyor olmam olabilir, ancak bu sorunu nasıl çözeceğimi bilmiyorum
Sherman Szeto

1
HttpClient, IDisposable uygular, bu nedenle onu bir using deyimine sarmak daha iyidir.
Payam

2
@Payam buna uygulayan doğrudur ederken IDisposablebir alanına kaydırmak gerektiğini usingaçıklamada. Bu, kuralın nadir bir istisnasıdır. Daha fazla bilgi için bu gönderiye
maxshuty

63

Kullanmak istemiyorsanız , kodu eşzamanlı olarak çalışmaya zorlamak için asyncekleyebilirsiniz .Result:

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;
 }  

2
@nbushnell, PostAsync'inize .Result ekleyerek onu async yapmıyor
Mike

6
@Mike, nbushnell'in söylediği bu değil mi? :-)
PoeHaH

Tip ne için response? Benzer bir kodum var ama responseglobal yapmam gerekiyor, bu yüzden türe ihtiyacım var. Teşekkürler.
Azurespot

1
@AzureSpot: De tür yanıt HttpResponseMessage'dır.
RWC
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.