Blazor 0.6.0会“清除”Flurl的兼容性?

9

在将Blazor从0.5.1版本(具有可用的Flurl)更新到0.6.0版本后,通过Flurl进行的调用会抛出异常:

WASM: [Flurl.Http.FlurlHttpException] Call failed. Cannot invoke method 
because it was wiped. See stack trace for details.

该项目创建了一个HttpClientFactory,该工厂获取Blazor的HttpClient以供Flurl使用:
使用HttpClientFactoryForBlazor创建带有Blazor的HttpClient(http)的FlurlClient:
IFlurlClient c = new FlurlClient() { Settings = new Flurl.Http.Configuration.ClientFlurlHttpSettings { HttpClientFactory = new HttpClientFactoryForBlazor(http) }};

使用FlurlClient (c) 的例子,可以通过Flurl的扩展方法 "IFlurlRequest.WithClient(c);" 来实现。
private class HttpClientFactoryForBlazor : Flurl.Http.Configuration.IHttpClientFactory
{
    private readonly HttpClient httpClient;

    public HttpClientFactoryForBlazor(HttpClient httpClient)
    {
        this.httpClient = httpClient;
    }

    public virtual HttpClient CreateHttpClient(HttpMessageHandler handler)
    {
        return this.httpClient;
    }
}

因此,似乎这种方法不再起作用。

有人知道如何使Blazor 0.6.0中的Flurl工作吗?

调用堆栈是:

WASM: [Flurl.Http.FlurlHttpException] Call failed. Cannot invoke method because it was wiped. See stack trace for details. GET http://srv01.servicegrid.eu:4455/API/Status?forceLoadDbs=False blazor.webassembly.js:1:32098
WASM:   at Flurl.Http.FlurlRequest.HandleExceptionAsync (Flurl.Http.HttpCall call, System.Exception ex, System.Threading.CancellationToken token) <0x26945b8 + 0x001c2> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM:   at Flurl.Http.FlurlRequest.SendAsync (System.Net.Http.HttpMethod verb, System.Net.Http.HttpContent content, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpCompletionOption completionOption) <0x2665d30 + 0x005e6> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM:   at Flurl.Http.FlurlRequest.SendAsync (System.Net.Http.HttpMethod verb, System.Net.Http.HttpContent content, System.Threading.CancellationToken cancellationToken, System.Net.Http.HttpCompletionOption completionOption) <0x2665d30 + 0x0079a> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM:   at Flurl.Http.HttpResponseMessageExtensions.ReceiveJson[T] (System.Threading.Tasks.Task`1[TResult] response) <0x26a2180 + 0x000d6> in <c38761af4558433f81b1691eb86a1548>:0 blazor.webassembly.js:1:32098
WASM:   at DotNetFabrik.FlurlExtensions.FlurlRequestExtensions.HandleWebApiExceptions[T] (System.Threading.Tasks.Task`1[TResult] task) <0x26a43f8 + 0x000e2> in <8c1e6df9d3f545cd831ff49915df2d85>:0 blazor.webassembly.js:1:32098
WASM:   at DotNetFabrik.FlurlExtensions.FlurlRequestExtensions.HandleWebApiExceptions[T] (System.Threading.Tasks.Task`1[TResult] task) <0x26a43f8 + 0x00264> in <8c1e6df9d3f545cd831ff49915df2d85>:0 blazor.webassembly.js:1:32098
WASM:   at BlazorCoreDMSTools.CommunicationService.CommunicationService.SetTokenAsync (System.String token, System.String database, System.String serverUri) <0x260dc60 + 0x00d9e> in <cb925648b50340888772566fbaeac465>:0 

你能提供异常的调用堆栈吗?我可能需要看到它抛出的确切位置,以便提供有效的修复/解决方法。 - Todd Menier
@ToddMenier 已添加调用堆栈。希望您能找到解决方案 - Blazor 和 Flurl 都是很棒的工具,在过去几个月中表现出色。 - Sascha
2个回答

12

为了提供一些背景,Blazor团队正在大幅减少应用程序的占用空间,并采取一些不寻常的措施来做到这一点。简而言之,他们通过“擦除”HttpClientHandler将其减少了约20%。

擦除的意思是“使用单个throw指令替换指定的方法体”。这样做(而不是完全删除该方法)意味着程序集保留了完全标准的API界面,如果您尝试使用其中一个已被擦除的方法,则会得到一个易于理解的异常堆栈跟踪,告诉您正在尝试调用哪个已被擦除的方法。

这就是你遇到的问题:Blazor仍然知道编译目的中的HttpClientHandler,但如果您(或在这种情况下兼容库)尝试使用它,它将抛出运行时异常。

但是,HttpClient必须包装HttpMessageHandler的某些实现,而Blazor有自己的实现:BrowserHttpMessageHandler。而且,Flurl提供了一种通过其HttpClientFactory轻松交换它的方法。但是,您无需传递HttpClient实例或实现CreateHttpClient。相反,继承DefaultHttpClientFactory并仅覆盖CreateMessageHandler

private class HttpClientFactoryForBlazor : DefaultHttpClientFactory
{
    public override HttpMessageHandler CreateMessageHandler()
    {
        return new BrowserHttpMessageHandler();
    }
}

我还建议您在应用启动时全局注册它一次,而不是每次创建 FlurlClient 时都注册:

FlurlHttp.Configure(settings =>
{
    settings.HttpClientFactory = new HttpClientFactoryForBlazor();
});

需要注意的是,Blazor仍处于实验阶段,并且BrowserHttpMessageHandler可能会在未来的版本中被弃用,因此请注意这可能只是一个临时解决方法。


5
哎呀,我不确定维护一个无法运行的“API surface”有什么意义。相比之下,我更愿意在 IDE 中“定位”并获取错误信息。我真心希望 Blazor 能够成功,但是像这样的问题令人担忧。 - Richard Collette
3
BrowserHttpMessageHandler现在更名为WebAssemblyHttpMessageHandler,可以直接替换之前的代码继续使用。具体信息见链接:https://github.com/aspnet/AspNetCore/commit/ceb1c8e562562b2655622b571d2a9ad083806ad5 - springy76
我已经应用了上述修复方法,在模拟测试中可以正常工作,但是当我尝试在带有头信息的 Azure 函数上运行时,它没有起作用。 - Robin

1

目前在我的3.0预览5中,BrowserHttpMessageHandler已经不存在了。这是我目前的解决方法,只需不使用任何HttpMessageHandler。据我所知,目前还没有出现任何问题,但并不确定是否适用于所有情况:

class BlazorHttpClientFactory : DefaultHttpClientFactory
{

    public override HttpClient CreateHttpClient(HttpMessageHandler handler)
    {
        return new HttpClient();
    }

    public override HttpMessageHandler CreateMessageHandler()
    {
        return null;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接