After updating Blazor from 0.5.1 (with working Flurl) to 0.6.0, calls via flurl throw an exception:
WASM: [Flurl.Http.FlurlHttpException] Call failed. Cannot invoke method
because it was wiped. See stack trace for details.
The project creates a HttpClientFactory which gets Blazor's HttpClient for being used by Flurl:
Create FlurlClient with Blazor's HttpClient (http) using HttpClientFactoryForBlazor:
IFlurlClient c = new FlurlClient() { Settings = new Flurl.Http.Configuration.ClientFlurlHttpSettings { HttpClientFactory = new HttpClientFactoryForBlazor(http) }};
Use the FlurlClient (c) for example by via Flurl's extensionmethod "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;
}
}
So, it seems like this approach does no longer work.
Does anybody know how to make Flurl with Blazor 0.6.0 work?
Call-Stack is:
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
Just for some background, the Blazor team is in the process of significantly reducing the app's footprint, and resorting to some unusual measures to do so. In a nutshell, they've reduced it by about 20% by "wiping" HttpClientHandler
.
wipe means "replace specified method bodies with a single throw instruction". Doing this (instead of actually removing the method entirely) means that the assembly retains a completely standard API surface, and if you try to use one of the wiped methods, you get an easy-to-understand exception stack trace that tells you which wiped method you're trying to call.
This is what you've bumped up against: Blazor is still aware of HttpClientHandler
for compilation purposes, but will throw a runtime exception if you (or in this case a compatible library) try to use it.
But HttpClient
must wrap some implementation of HttpMessageHandler
Blazor has its own: BrowserHttpMessageHandler
. And Flurl provides an easy way to swap this in via its HttpClientFactory
. But you don't need to pass in an HttpClient
instance or implement CreateHttpClient
. Instead, inherit from DefaultHttpClientFactory
and just override CreateMessageHandler
:
private class HttpClientFactoryForBlazor : DefaultHttpClientFactory
{
public override HttpMessageHandler CreateMessageHandler()
{
return new BrowserHttpMessageHandler();
}
}
I'd also recommend registering this once globally on app startup, rather than every time you create a FlurlClient
:
FlurlHttp.Configure(settings =>
{
settings.HttpClientFactory = new HttpClientFactoryForBlazor();
});
It should also be noted that Blazor is still experimental and that BrowserHttpMessageHandler
may be deprecated in a future release, so expect that this could be just a temporary work-around.
Currently in my 3.0 preview 5, BrowserHttpMessageHandler
is not there anymore. Here is my current fix by simply not using any HttpMessageHandler
. As far as I am aware, no problem happens to me yet, but I am not sure in all use cases:
class BlazorHttpClientFactory : DefaultHttpClientFactory
{
public override HttpClient CreateHttpClient(HttpMessageHandler handler)
{
return new HttpClient();
}
public override HttpMessageHandler CreateMessageHandler()
{
return null;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With