【问题标题】:Blazor HttpClient stuck in GetAsyncBlazor HttpClient 卡在 GetAsync 中
【发布时间】:2019-05-02 13:48:10
【问题描述】:

我正在针对 Blazor 3.0.0-preview4-19216-03 的客户端 Blazor 应用程序进行测试

剃须刀页面:

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

依赖注入:

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

服务:

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

每当我点击增量计数时,什么都没有发生,并且对GetWeb 的服务调用会卡在GetAsync 调用中。

更新

如果我在 Chrome 的 WASM 调试器中调试 WebCrawler 服务,则会发出请求

但是响应部分是空的:

【问题讨论】:

  • 你在哪里添加HttpClient?还是自动添加的?
  • 它由 Blazor 注入并进行了调整,使其可以在 WASM 环境中工作。我自己创建了一个新的 HttpClient 实例,也没有工作。
  • 我怀疑它与async void 有关。我正在阅读更多内容以确保/

标签: c# blazor webassembly blazor-webassembly


【解决方案1】:

您只能从客户端应用访问您自己的来源或支持 CORS 的网站。

为了验证这是您的问题,您可以尝试https://postman-echo.com/response-headers?foo1=bar1&amp;access-control-allow-origin=*,这可能有效。

但它只适用于该网站。您通常无法控制响应标头。这不是解决办法。

因此,Blazor 客户端对于网络爬虫来说并不是一个好的平台。 JS 或 WASM 上的任何应用程序也是如此。

Blazor 服务器端应该没有问题。或者使用 Web API 服务。


您可以在 Wasm 应用中尝试:

@page "/"
@inject HttpClient Http

<h1>Hello, world!</h1>
<div>
    <button class="btn btn-primary" @onclick="GetData1">With CORS</button>
    <button class="btn btn-primary" @onclick="GetData2">No CORS</button>
</div>
<div>@json</div>

@code
{
    string json = ".";

    async Task GetData1()
    {        
        json = await Http.GetStringAsync(
         "https://postman-echo.com/response-headers" + 
         "?foo1=bar1&access-control-allow-origin=*");
    }

    async Task GetData2()
    {
        json = "Getting w/o CORS... ";
        json = await Http.GetStringAsync(
          "https://postman-echo.com/response-headers?foo1=bar1");
    }
}

【讨论】:

  • 这是一个 CORS 问题,使用带有 'access-control-allow-origin=*' 的 URL 完成了工作。将测试 Blazor Serverside,因为它看起来更健壮。感谢您的回答!
  • 哦,是的,它是如何工作的?请赐教。上面 url 中的 'access-control-allow-origin=*' 只是一个查询字符串参数,可以像其他两个参数一样回显。只需将此 url 放在浏览器的地址栏中,然后按 enter 即可查看返回的 json。您可以轻松地将最后一个参数替换为:'allow-origin=*'
  • 顺便说一句,您当然应该学习和测试服务器端 Blazor,但这与问题无关。正如我已经说过的,问题不在于 Blazor 或 HttpClient。
  • @Henk Holterman,这是什么:'access-control-allow-origin=*' 你想在这里做什么;)“access-control-allow-origin”是提供的响应标头由服务器
  • 您还没有阅读postman-echo.com 上的文档。您是否至少注意到 URL 的 /response-headers 部分?
【解决方案2】:

我怀疑这与async void 有关。

您需要让处理程序返回 Task,而不是 void

例如

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

框架中提供了对异步事件处理程序的支持

参考GitHub Issue: Calling an async function via onclick

【讨论】:

  • 您好 Nkosi,感谢您的回答,但不幸的是它不起作用,我添加了“私有异步任务 IncrementCount()”,但没有区别。
  • @Nkosi,您可以将 async void 用于事件。我不确定 this.StateHasChanged(); call 是必要的,因为这个方法总是在事件引发后自动调用。
  • Blazor 支持 async Task 事件,非常可取。当您使用 async void 时,也会以 StateHasChanged() 结束,因为框架不会(不能)这样做。
【解决方案3】:

这可能是由于您无法控制的服务器上的 CORS 配置问题。我认为这个问题与 Blazor 无关。要验证这一点,请在您的应用程序中定义一个本地 json 文件,并使用您在应用程序中使用的相同代码访问它。

希望这行得通...

更新

我不完全确定请求是否由于 CORS 配置问题而失败,至少不完全是。在我看来,它也与 SSL/TLS 有关。 此错误消息由 Fiddler 发出:

fiddler.network.https> HTTPS 握手失败。 System.IO.IOException 无法从传输中读取数据 连接:现有连接被远程强行关闭 主持人。

底层连接已关闭,无法为 SSL/TLS 安全通道建立信任关系。

我想我会在 github 上发布这个问题,以便更好地了解这里出了什么问题。

【讨论】:

  • “它由 Blazor 注入并进行了调整,因此它可以在 WASM 环境中工作”,@etragu 说。对不起,没有区别...我之前没有注意到代码...
猜你喜欢
  • 2019-08-29
  • 2016-04-20
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-04
  • 1970-01-01
相关资源
最近更新 更多