Blazor HttpClient stuck in GetAsync

2020-07-23 04:14发布

问题:

I'm making test in a Client Side Blazor app targeting Blazor 3.0.0-preview4-19216-03

The razor page:

@page "/counter"
@using BlazorServiceTest
@inject IWebCrawlServiceAsync WebCrawler

<h1>Counter</h1>

<p>Current count: @debug</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

@functions {
    string debug = "";

    async void IncrementCount()
    {
        debug = await WebCrawler.GetWeb();
    }
}

The dependency injection:

using BlazorServiceTest;
using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace BlazorServicesTest
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {   
            services.AddSingleton<IWebCrawlServiceAsync, WebCrawlServiceAsync>();            
        }

        public void Configure(IComponentsApplicationBuilder app)
        {
            app.AddComponent<App>("app");
        }
    }
}

The Service:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace BlazorServiceTest
{
    public interface IWebCrawlServiceAsync
    {
        Task<string> GetWeb();
    }

    public class WebCrawlServiceAsync : IWebCrawlServiceAsync
    {
        private HttpClient _client;    

        public WebCrawlServiceAsync(HttpClient client)
        {
            _client = client;
        }

        public async Task<string> GetWeb()
        {
            var response = await _client.GetAsync("https://postman-echo.com/response-headers?foo1=bar1&foo2=bar2");
            var result = await response.Content.ReadAsStringAsync();
            return result;
        }
    }
}

Whenever I click in Increment count nothing happens and the service call to GetWeb it's stuck in the GetAsync call.

UPDATE

If I debug the service WebCrawler in Chrome's WASM debugger, he request is being made

But the response section is empty:

回答1:

From a client-side app you can only acces your own origin or sites that support CORS.

In order to verify that this is your issue, you can try https://postman-echo.com/response-headers?foo1=bar1&access-control-allow-origin=*, that might work.

But it will only work for that site. You normally have no control over the response headers. It's not a fix.

So, Blazor client-side is just not a good platform for a webcrawler. The same goes for any app on JS or WASM.

Blazor server-side should have no problems. Or use a Web API service.



回答2:

I suspect it has something to do with the async void.

You need to have the handler return a Task, not void

For example

@page "/counter"
@using BlazorServiceTest
@inject IWebCrawlServiceAsync WebCrawler

<h1>Counter</h1>

<p>Current count: @debug</p>

<button class="btn btn-primary" onclick="@IncrementCount">Click me</button>

@functions {
    string debug { get; set; } = "";

    async Task IncrementCount() { //<-- Note Change here
        debug = await WebCrawler.GetWeb();
    }
}

support for async event handler is available in the framework

Reference GitHub Issue: Calling an async function via onclick



回答3:

This may be due to a CORS configuration issue on the server of which you have no control. I believe that this issue has nothing to do with Blazor. To verify this, define a local json file in your app and access it with the same code you use in your application.

Hope this works...

UPDATE

I'm not entirely sure that the request fails due to CORS configuration issue, at least not exclusively. It seems to me that it is also related to SSL/TLS. This error message was issued by Fiddler:

fiddler.network.https> HTTPS handshake to failed. System.IO.IOException Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. < An existing connection was forcibly closed by the remote host

The underlying connection is closed and no trust relationship can be established for the SSL/TLS secure channel.

I guess I'll post this question in github to get a better understanding of what went wrong here.