How to get content body from a httpclient call?
Asked Answered
C

2

163

I've been trying to figure out how to read the contents of a httpclient call, and I can't seem to get it. The response status I get is 200, but I can't figure out how to get to the actual Json being returned, which is all I need!

The following is my code:

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

And I am getting it just calling it from a method:

Task<string> result =  GetResponseString(text);

And This is what I get

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>

Update: This is my current code per Nathan's response below

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

And I call it from this method....

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

And it keeps running forever, It hits the line var model = JsonConvert.DeserializeObject<SentimentJsonModel>(result.Result); Once, and it continues to go without stopping at another breakpoint.

When I pause execution, It say

Id = Cannot evaluate expression because the code of the current method is optimized., Status = Cannot evaluate expression because the code of the current method is optimized., Method = Cannot evaluate expression because the code of the current method is optimized., Result = Cannot evaluate expression because the code of the current method is optimized.

.. I Continue execution, but it just runs forever. Not sure what the problem is

Carlita answered 27/10, 2014 at 22:6 Comment(4)
Where and how is _numRetries defined?Gauntlet
Its in the scope of the class and is initialized with a 0 in the constructor. AnalyzeSingle() is the only place I use it.Carlita
Are you running in Debug mode? The optimized issue might be because you are running in Release mode.Gauntlet
I am currently on Debug/ iisExpressCarlita
G
251

The way you are using await/async is poor at best, and it makes it hard to follow. You are mixing await with Task'1.Result, which is just confusing. However, it looks like you are looking at a final task result, rather than the contents.

I've rewritten your function and function call, which should fix your issue:

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

And your final function call:

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

Or even better:

var finalResult = await GetResponseString(text);
Gauntlet answered 27/10, 2014 at 22:40 Comment(5)
Im still having issues. I updated my problem on the original post. The issue may be that I am coding for synchronous execution, but Im not sure how to solve that problemCarlita
@Payam while it's true that it implements IDisposable you should not wrap it in a using statement. It's a rare exception to the rule. See this post for more information: aspnetmonsters.com/2016/08/2016-08-27-httpclientwrongPreachment
Any one else had extra "" as part of the string? This is the last value I got stored in the variable: "\"9F4692CB\"". So at the end I will get: "9F4692CB" displayed in the view. Any suggestion to get rif of those extra ""in the string value? Thanks.Devon
@Devon is it possible that the API is returning a JSON string? If so, that's where the extra quotes are coming from, and you can get rid of the quotes by serializing it. You could also update the API to only return a string instead of a JSON string object.Gauntlet
Thanks @NathanA, it is actually returning JSON. I ended up changing the returning value to a Class object instead of returning a string. Thanks for the suggestion of serializing it, it should work.Devon
F
86

If you are not wanting to use async you can add .Result to force the code to execute synchronously:

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;
 }  
Frankish answered 13/7, 2015 at 21:44 Comment(5)
@Frankish adding .Result to your PostAsync makes the it non-asyncPrefatory
@Prefatory isn't that what nbushnell is saying? :-)Airport
What is the type for response? I have a similar code but I need to make response global, so I need the type. Thanks.Gotama
@AzureSpot: De type of response is HttpResponseMessage.Crowson
Don't use the Response property. If you must be non-async, use GetAwaiter.GetResponse().Mojave

© 2022 - 2024 — McMap. All rights reserved.