จะรับเนื้อหาจากการโทร httpclient ได้อย่างไร


111

ฉันพยายามหาวิธีอ่านเนื้อหาของการโทร httpclient แล้ว แต่ดูเหมือนจะไม่เข้าใจ สถานะการตอบกลับที่ฉันได้รับคือ 200 แต่ฉันคิดไม่ออกว่าจะส่งคืน Json ที่แท้จริงได้อย่างไรซึ่งทั้งหมดที่ฉันต้องการ!

ต่อไปนี้เป็นรหัสของฉัน:

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

และฉันได้รับมันเพียงแค่เรียกมันจากวิธีการ:

Task<string> result =  GetResponseString(text);

และนี่คือสิ่งที่ฉันได้รับ

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>

อัปเดต:นี่คือรหัสปัจจุบันของฉันตามคำตอบของนาธานด้านล่าง

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

และฉันเรียกมันจากวิธีนี้ ....

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

และมันยังคงทำงานตลอดไปมันเข้าเส้น var model = JsonConvert.DeserializeObject<SentimentJsonModel>(result.Result); ครั้งเดียวและมันจะไปต่อโดยไม่หยุดที่จุดพักอื่น

เมื่อฉันหยุดการดำเนินการชั่วคราวมันจะพูด

Id = ไม่สามารถประเมินนิพจน์เนื่องจากโค้ดของเมธอดปัจจุบันได้รับการปรับให้เหมาะสม, สถานะ = ไม่สามารถประเมินนิพจน์เนื่องจากโค้ดของเมธอดปัจจุบันได้รับการปรับให้เหมาะสม, Method = ไม่สามารถประเมินนิพจน์เนื่องจากโค้ดของเมธอดปัจจุบันได้รับการปรับให้เหมาะสม, ผลลัพธ์ = ไม่สามารถประเมินนิพจน์เนื่องจากโค้ดของวิธีการปัจจุบันได้รับการปรับให้เหมาะสม

.. ฉันดำเนินการต่อ แต่มันก็ดำเนินไปตลอดกาล ไม่แน่ใจว่าปัญหาคืออะไร


_numRetries กำหนดไว้ที่ไหนและอย่างไร
Nathan A

อยู่ในขอบเขตของคลาสและเริ่มต้นด้วย 0 ในตัวสร้าง AnalyzeSingle () เป็นที่เดียวที่ฉันใช้
Sherman Szeto

คุณกำลังทำงานในโหมดแก้ไขข้อบกพร่องหรือไม่ ปัญหาที่ได้รับการปรับให้เหมาะสมอาจเป็นเพราะคุณกำลังทำงานในโหมดเผยแพร่
Nathan A

ขณะนี้ฉันใช้ Debug / iisExpress
Sherman Szeto

คำตอบ:


178

วิธีที่คุณใช้ await / async นั้นแย่ที่สุดและทำให้ยากต่อการติดตาม คุณกำลังผสมawaitกับTask'1.Resultซึ่งเป็นเพียงความสับสน อย่างไรก็ตามดูเหมือนว่าคุณกำลังดูผลลัพธ์ของงานขั้นสุดท้ายมากกว่าเนื้อหา

ฉันได้เขียนฟังก์ชันและการเรียกฟังก์ชันของคุณใหม่แล้วซึ่งควรแก้ไขปัญหาของคุณ:

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

และการเรียกใช้ฟังก์ชันสุดท้ายของคุณ:

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

หรือดีกว่า:

var finalResult = await GetResponseString(text);

ขอบคุณ !! ฉันพยายามหาว่า async / await ทำงานอย่างไรในช่วงสองสามชั่วโมงที่ผ่านมา (MSDN + stackoverflow) แต่เห็นได้ชัดว่าฉันยังไม่เข้าใจมันทั้งหมด มีแหล่งข้อมูลที่คุณจะแนะนำหรือไม่?
Sherman Szeto

1
เพียงแค่เล่นกับมันและคุณจะได้รับความวุ่นวายในที่สุด เป็นแนวคิดขนาดใหญ่ที่จะเข้าใจทั้งหมดในครั้งเดียว
Nathan A

ฉันยังคงมีปัญหา ฉันอัปเดตปัญหาของฉันในโพสต์เดิม ปัญหาอาจเป็นเพราะฉันกำลังเข้ารหัสสำหรับการดำเนินการแบบซิงโครนัส แต่ฉันไม่แน่ใจว่าจะแก้ปัญหานั้นอย่างไร
Sherman Szeto

1
HttpClient ใช้ IDisposable ดังนั้นจึงเป็นการดีกว่าที่จะรวมไว้ในคำสั่งโดยใช้
พยาม

2
@Payam ในขณะที่มันเป็นเรื่องจริงที่IDisposableคุณไม่ควรห่อไว้ในusingคำสั่ง เป็นข้อยกเว้นที่หายากสำหรับกฎ ดูโพสต์นี้สำหรับข้อมูลเพิ่มเติม: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

64

หากคุณไม่ต้องการใช้asyncคุณสามารถเพิ่ม.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 ของคุณทำให้มันไม่เหมือนเดิม
Mike

6
@ ไมค์ไม่ว่า nbushnell พูดอะไร? :-)
PoeHaH

ประเภทresponseคืออะไร? ฉันมีรหัสที่คล้ายกัน แต่ฉันต้องการสร้างresponseทั่วโลกดังนั้นฉันจึงต้องการประเภท ขอบคุณ.
Azurespot

1
@AzureSpot: ประเภทของการตอบสนอง De คือ HttpResponseMessage
RWC
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.