HttpClient GetAsync not working as expected
Asked Answered
E

5

5

When testing my web API with Postman my API get executes fine!

When it comes to running the code with HttpClient in my client application the code executes without error but without the expected result on the server. What could be happening?

From my client application:

private string GetResponseFromURI(Uri u)
{
    var response = "";
    HttpResponseMessage result;
    using (var client = new HttpClient())
    {
        Task task = Task.Run(async () =>
        {
            result = await client.GetAsync(u);
            if (result.IsSuccessStatusCode)
            {
                response = await result.Content.ReadAsStringAsync();
            }
        });
        task.Wait();
    }
    return response;
}

Here is the API controller:

[Route("api/[controller]")]
public class CartsController : Controller
{
    private readonly ICartRepository _cartRepo;

    public CartsController(ICartRepository cartRepo)
    {
        _cartRepo = cartRepo;
    }

    [HttpGet]
    public string GetTodays()
    {
        return _cartRepo.GetTodaysCarts();
    }

    [HttpGet]
    [Route("Add")]
    public string GetIncrement()
    {
        var cart = new CountedCarts();
        _cartRepo.Add(cart);

        return _cartRepo.GetTodaysCarts();
    }

    [HttpGet]
    [Route("Remove")]
    public string GetDecrement()
    {
        _cartRepo.RemoveLast();
        return _cartRepo.GetTodaysCarts();
    }


}

Note these API calls work as expected when called from Postman.

Elwandaelwee answered 31/3, 2017 at 19:18 Comment(6)
Word of warning, HttpClient is meant to be reused as a single instance. Wrapping it in a using statement or newing one up for every call can have adverse effects.Outsize
Use Fiddler to compare both Requests. Probably missing Headers.Symphonist
Thanks for the warning @Outsize I pulled the httpclient out into a static field, same results.Elwandaelwee
Sorry, I did not mean to imply that would fix your issue. I just wanted to point out that HttpClient is one of few instances where you wouldn't want to dispose after every use.Outsize
I just wanted to point out, any 'adverse' effects from disposing of HTTPClient, in my case, did not attribute to the issue.Elwandaelwee
How do you access those action methods - GetTodays, GetIncrement and GetDecrement? Could you show the URLs?Aguiar
S
24

You shouldn't use await with client.GetAsync, It's managed by .Net platform, because you can only send one request at the time.

just use it like this

var response = client.GetAsync("URL").Result;  // Blocking call!

            if (response.IsSuccessStatusCode)
            {
                // Parse the response body. Blocking!
                var dataObjects = response.Content.ReadAsAsync<object>().Result;

            }
            else
            {
                var result = $"{(int)response.StatusCode} ({response.ReasonPhrase})";
               // logger.WriteEntry(result, EventLogEntryType.Error, 40);
            }
Skyscraper answered 24/10, 2017 at 7:48 Comment(2)
i didn't understand why. but it works as you said, otherwise my debugger would stop on the await line and never catches back again! I guess I need to revise again how await and result work! .. Thanks you saved my dayFayfayal
This saved my day. My debugger was skipping the rest of the method after the await client.GetAsync(..).Bandeau
A
9

You are doing fire-and-forget approach. In your case, you need to wait for the result.

For example,

static async Task<string> GetResponseFromURI(Uri u)
{
    var response = "";
    using (var client = new HttpClient())
    {
        HttpResponseMessage result = await client.GetAsync(u);
        if (result.IsSuccessStatusCode)
        {
            response = await result.Content.ReadAsStringAsync();
        }
    }
    return response;
}

static void Main(string[] args)
{
    var t = Task.Run(() => GetResponseFromURI(new Uri("http://www.google.com")));
    t.Wait();

    Console.WriteLine(t.Result);
    Console.ReadLine();
}
Aguiar answered 31/3, 2017 at 19:29 Comment(4)
I implemented this and the behavior didn't change. I am starting to think i am using get when i should be using put. The path in the api is a get response that is incrementing a counter... it only works the first call.Elwandaelwee
Before we go any further, could you check with http://www.google.com URL?Aguiar
It does, it also "appears" to work using my Uri. When the Uri is called, the counter increments and the result is returned. I also have an api call for decrementing using a similar approach. It just isn't incrementing.Elwandaelwee
CartsController violates basic REST principle - HttpGet should not change anything on the server - idempotent and safe.Aguiar
S
1

Simple sample used to get page data.

public string GetPage(string url)
{
    HttpResponseMessage response = client.GetAsync(url).Result;

    if (response.IsSuccessStatusCode)
    {
        string page = response.Content.ReadAsStringAsync().Result;
        return "Successfully load page";
    }
    else
    {
        return "Invalid Page url requested";
    }
}
Shippee answered 25/8, 2021 at 8:45 Comment(0)
T
0

I've had a problem with chace control when using httpclient.

HttpBaseProtocalFilter^ filter = ref new HttpBaseProtocolFilter();
filter->CacheControl->ReadBehavior = Windows::Web::Http::Filters::HttpCacheReadBehavior::MostRecent;
HttpClient^ httpClient = ref new HttpClient(filter);

I'm not really sure what the expected results are or what results your getting at all so this is really just a guessing game right now.

When I POST something using HttpClient I found adding headers by hand seemed to work more often than using default headers.

auto httpClient = ref new HttpClient();
Windows::Web::Http::Headers::HttpMediaTypeHeaderValue^ type = ref new Windows::Web::http::Headers::HttpMediaTypeHeaderValue("application/json");
content->Headers->ContentType = type;

If I don't do these 2 things I found, for me anyways, that half the time my web requests were either not actually being sent or the headers were all messed up and the other half of the time it worked perfectly.

I just read a comment where you said it would only fire once, that makes me think it is the cachecontrol. I think what happens is something (Windows?) sees 2 requests being sent that are the exact same, so to speed things up it just assumes the same answer and never actually sends the request a 2nd time

Typhoon answered 19/5, 2017 at 21:39 Comment(0)
P
0

Since you are able to hit the API endpoint with Postman, you should be able to get the working code of HttpClient for the same in Postman. Just click "</>" on the right-hand side. It gives code in many languages including C#'s HttpClient

Plotinus answered 15/6, 2023 at 4:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.