將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?
Call-Stack是:
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
僅出於某些背景,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
,因此希望這只是暫時的解決方法。
當前在我的3.0預覽5中,不再存在BrowserHttpMessageHandler
。這是我目前的解決方法,只需不使用任何HttpMessageHandler
。據我所知,我還沒有遇到任何問題,但是我不確定在所有用例中:
class BlazorHttpClientFactory : DefaultHttpClientFactory
{
public override HttpClient CreateHttpClient(HttpMessageHandler handler)
{
return new HttpClient();
}
public override HttpMessageHandler CreateMessageHandler()
{
return null;
}
}