0

I try to make web web api client by this example and it works great: https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

than I try to make it in my web form, so when user hit button in browser api get called. It executes and everything is fine but page at the end just loading and loading. I also put ConfigureAwait(false); whereever await appers, which is mention here: HttpClient.GetAsync(...) never returns when using await/async

so how can I properly call api below on button click?

Please for help...

public partial class test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    public class Product
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
        public string Category { get; set; }
    }

    static HttpClient client = new HttpClient();

    static void ShowProduct(Product product)
    {
        Console.WriteLine($"Name: {product.Name}\tPrice: " +
            $"{product.Price}\tCategory: {product.Category}");
    }

    static async Task<Uri> CreateProductAsync(Product product)
    {
        HttpResponseMessage response = await client.PostAsJsonAsync("api/products", product).ConfigureAwait(false); ;
        response.EnsureSuccessStatusCode();

        // return URI of the created resource.
        return response.Headers.Location;
    }

    static async Task<Product> GetProductAsync(string path)
    {
        Product product = null;
        HttpResponseMessage response = await client.GetAsync(path).ConfigureAwait(false);
        if (response.IsSuccessStatusCode)
        {
            product = await response.Content.ReadAsAsync<Product>().ConfigureAwait(false);
        }
        return product;
    }

    static async Task RunAsync()
    {
        // Update port # in the following line.
        client.BaseAddress = new Uri("http://localhost:64195/");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        try
        {
            // Create a new product
            Product product = new Product
            {
                Name = "Gizmo",
                Price = 100,
                Category = "Widgets"
            };

            var url = await CreateProductAsync(product).ConfigureAwait(false); ;
            Console.WriteLine($"Created at {url}");

            // Get the product
            product = await GetProductAsync(url.PathAndQuery);
            ShowProduct(product);


        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

        Console.ReadLine();
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        RunAsync().GetAwaiter().GetResult();
    }
}
Jure Možina
  • 11
  • 1
  • 4
  • Don't use `ConfigureAwait(false)` as a way to avoid deadlocks. [It doesn't always save you](https://contrivedexample.com/2017/12/04/configureawait-sometimes-saves-the-day-everytime/). Make the click event async also so you can await instead of block. If you don't await then you do a "fire-and-forget" operation - you'll never let the system have a chance to `ShowProduct()`. – Crowcoder Jun 22 '18 at 11:57
  • sorry for late reply and thanks for that, but if remove ConfigureAwait(false) and put async: protected async void Button1_Click(object sender, EventArgs e) { RunAsync().GetAwaiter().GetResult(); } than i got worning: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls... – Jure Možina Jul 02 '18 at 12:26
  • The point of making the event async is so you can await. Don't block with GetResult. You can still ConfigureAwait(false), just don't always rely on it to prevent deadlocks. – Crowcoder Jul 02 '18 at 14:06
  • ok, but how than function Button1_Click should be written in right way? – Jure Možina Jul 03 '18 at 05:13

0 Answers0