Làm cách nào để lấy nội dung từ cuộc gọi httpclient?


108

Tôi đang cố gắng tìm cách đọc nội dung của cuộc gọi httpclient và dường như tôi không thể hiểu được. Trạng thái phản hồi mà tôi nhận được là 200, nhưng tôi không thể tìm ra cách để trả về Json thực tế đang được trả lại, đó là tất cả những gì tôi cần!

Sau đây là mã của tôi:

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

Và tôi nhận được nó chỉ cần gọi nó từ một phương thức:

Task<string> result =  GetResponseString(text);

Và đây là những gì tôi nhận được

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>

Cập nhật: Đây là mã hiện tại của tôi theo phản hồi của Nathan bên dưới

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

Và tôi gọi nó từ phương pháp này….

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

Và nó tiếp tục chạy mãi mãi, Nó chạm đến dòng var model = JsonConvert.DeserializeObject<SentimentJsonModel>(result.Result); Một lần, và nó tiếp tục chạy mà không dừng lại ở một điểm dừng khác.

Khi tôi tạm dừng thực hiện, Nó nói

Id = Không thể đánh giá biểu thức vì mã của phương thức hiện tại được tối ưu hóa., Trạng thái = Không thể đánh giá biểu thức vì mã của phương thức hiện tại được tối ưu hóa., Phương thức = Không thể đánh giá biểu thức vì mã của phương pháp hiện tại được tối ưu hóa., Kết quả = Không thể đánh giá biểu thức vì mã của phương thức hiện tại được tối ưu hóa.

.. Tôi Tiếp tục thực hiện, nhưng nó chỉ chạy mãi mãi. Không chắc vấn đề là gì


_NumRetries được định nghĩa ở đâu và như thế nào?
Nathan A

Nó nằm trong phạm vi của lớp và được khởi tạo bằng 0 trong hàm tạo. AnalyzeSingle () là nơi duy nhất tôi sử dụng nó.
Sherman Szeto

Bạn có đang chạy ở chế độ Gỡ lỗi không? Vấn đề được tối ưu hóa có thể là do bạn đang chạy ở chế độ Phát hành.
Nathan A

Tôi hiện đang ở trên Debug / iisExpress
Sherman Szeto,

Câu trả lời:


176

Cách bạn đang sử dụng await / async là kém nhất và khiến bạn khó theo dõi. Bạn đang trộn lẫn awaitvới Task'1.Result, điều đó chỉ là khó hiểu. Tuy nhiên, có vẻ như bạn đang xem xét kết quả nhiệm vụ cuối cùng, thay vì nội dung.

Tôi đã viết lại hàm và lệnh gọi hàm của bạn, cách này sẽ khắc phục sự cố của bạn:

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

Và lệnh gọi hàm cuối cùng của bạn:

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

Hoặc thậm chí tốt hơn:

var finalResult = await GetResponseString(text);

Cảm ơn!! Tôi đã cố gắng tìm hiểu cách hoạt động của async / await trong vài giờ qua (MSDN + stackoverflow), nhưng rõ ràng là tôi vẫn chưa hiểu đầy đủ về nó. Có tài nguyên nào bạn muốn đề xuất không?
Sherman Szeto

1
Chỉ cần tiếp tục chơi với nó và cuối cùng bạn sẽ hiểu được nó. Đó là một khái niệm lớn để nắm bắt tất cả cùng một lúc.
Nathan A

Tôi vẫn gặp sự cố. Tôi đã cập nhật vấn đề của mình trên bài đăng gốc. Vấn đề có thể mà tôi đang mã hóa để thực hiện đồng bộ, nhưng Im không chắc chắn làm thế nào để giải quyết vấn đề đó
Sherman Szeto

1
HttpClient triển khai IDisposable, vì vậy tốt hơn nên gói nó trong một câu lệnh using.
Payam

2
@Payam trong khi đúng là nó thực hiện, IDisposablebạn không nên gói nó trong một usingcâu lệnh. Đó là một ngoại lệ hiếm hoi đối với quy tắc. Xem bài đăng này để biết thêm thông tin: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
maxshuty

62

Nếu bạn không muốn sử dụng, asyncbạn có thể thêm .Resultđể buộc mã thực thi đồng bộ:

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 thêm .Result vào PostAsync của bạn làm cho nó không phải là async
Mike

6
@Mike không phải đó là những gì nbushnell đang nói? :-)
PoeHaH

Loại dùng để làm responsegì? Tôi có một mã tương tự nhưng tôi cần tạo responsetoàn cục, vì vậy tôi cần loại. Cảm ơn.
Azurespot

1
@AzureSpot: Loại phản hồi De là HttpResponseMessage.
RWC
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.