diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 6cb35269ddc..1b4c26eae94 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@ - 9.3.1-beta24 + 9.3.1-beta25 diff --git a/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs b/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs index e6961bc3989..57114bf3447 100644 --- a/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs +++ b/src/BootstrapBlazor/Components/ConnectionHub/ConnectionHub.cs @@ -51,8 +51,7 @@ protected override async Task InvokeInitAsync() Method = nameof(Callback), ConnectionId = Guid.NewGuid(), Interval = options.BeatInterval.TotalMilliseconds, - Url = "ip.axd", - BootstrapBlazorOptions.Value.WebClientOptions.EnableIpLocator + Url = "ip.axd" }); } } diff --git a/src/BootstrapBlazor/Extensions/JSModuleExtensions.cs b/src/BootstrapBlazor/Extensions/JSModuleExtensions.cs index 92d9049ad03..03276489e54 100644 --- a/src/BootstrapBlazor/Extensions/JSModuleExtensions.cs +++ b/src/BootstrapBlazor/Extensions/JSModuleExtensions.cs @@ -50,6 +50,7 @@ public static async Task LoadModule(this IJSRuntime jsRuntime, string { jSObjectReference = await jsRuntime.InvokeAsync(identifier: "import", fileName); } + catch (JSDisconnectedException) { } catch (JSException) { #if DEBUG @@ -58,6 +59,7 @@ public static async Task LoadModule(this IJSRuntime jsRuntime, string #endif } catch (OperationCanceledException) { } + catch (ObjectDisposedException) { } return new JSModule(jSObjectReference); } diff --git a/src/BootstrapBlazor/Services/WebClientService.cs b/src/BootstrapBlazor/Services/WebClientService.cs index 5512100f1e9..385684b9e7d 100644 --- a/src/BootstrapBlazor/Services/WebClientService.cs +++ b/src/BootstrapBlazor/Services/WebClientService.cs @@ -43,19 +43,17 @@ public async Task GetClientInfo() try { _jsModule ??= await runtime.LoadModuleByName("client"); - _interop ??= DotNetObjectReference.Create(this); - await _jsModule.InvokeVoidAsync("ping", "ip.axd", _interop, nameof(SetData), new + if (_jsModule != null) { - options.CurrentValue.WebClientOptions.EnableIpLocator - }); - - // 等待 SetData 方法执行完毕 - await _taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(3)); + _interop ??= DotNetObjectReference.Create(this); + await _jsModule.InvokeVoidAsync("ping", "ip.axd", _interop, nameof(SetData)); + // 等待 SetData 方法执行完毕 + await _taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(3)); + } } - catch (TimeoutException) { } catch (Exception ex) { - logger.LogError(ex, "method GetClientInfo failed"); + logger.LogError(ex, "{GetClientInfo} throw exception", nameof(GetClientInfo)); } // 补充 IP 地址信息 diff --git a/src/BootstrapBlazor/wwwroot/modules/client.js b/src/BootstrapBlazor/wwwroot/modules/client.js index 73bdab42dde..a608d7b9090 100644 --- a/src/BootstrapBlazor/wwwroot/modules/client.js +++ b/src/BootstrapBlazor/wwwroot/modules/client.js @@ -1,12 +1,12 @@ import "./browser.js" import { execute } from "./ajax.js" -export async function ping(url, invoke, method, options) { - const data = await getClientInfo(url, options); +export async function ping(url, invoke, method) { + const data = await getClientInfo(url); await invoke.invokeMethodAsync(method, data) } -export async function getClientInfo(url, options) { +export async function getClientInfo(url) { const info = browser() let data = { browser: info.browser + ' ' + info.version, @@ -17,14 +17,12 @@ export async function getClientInfo(url, options) { os: info.system + ' ' + info.systemVersion } - if (options.enableIpLocator === true) { - const result = await execute({ - method: 'GET', - url - }); - if (result) { - data.ip = result.Ip; - } + const result = await execute({ + method: 'GET', + url + }); + if (result) { + data.ip = result.Ip; } data.id = localStorage.getItem('bb_hub_connection_id') ?? result.Id; return data; diff --git a/src/BootstrapBlazor/wwwroot/modules/hub.js b/src/BootstrapBlazor/wwwroot/modules/hub.js index 95602948d2b..ac0923bbd8c 100644 --- a/src/BootstrapBlazor/wwwroot/modules/hub.js +++ b/src/BootstrapBlazor/wwwroot/modules/hub.js @@ -3,7 +3,7 @@ import Data from "./data.js" import EventHandler from "./event-handler.js"; export async function init(id, options) { - const { invoke, method, interval = 3000, url, connectionId, enableIpLocator } = options; + const { invoke, method, interval = 3000, url, connectionId } = options; const elKey = 'bb_hub_el_id'; if (localStorage.getItem(elKey) === null) { localStorage.setItem(elKey, id); @@ -34,7 +34,7 @@ export async function init(id, options) { } }); - const info = await getClientInfo(url, { enableIpLocator: enableIpLocator }); + const info = await getClientInfo(url); info.id = clientId; const callback = async () => { diff --git a/test/UnitTest/Extensions/JSModuleExtensionsTest.cs b/test/UnitTest/Extensions/JSModuleExtensionsTest.cs index 87422f31664..69f1c46aea9 100644 --- a/test/UnitTest/Extensions/JSModuleExtensionsTest.cs +++ b/test/UnitTest/Extensions/JSModuleExtensionsTest.cs @@ -21,6 +21,12 @@ public async Task LoadModule_Ok() var jsRuntime2 = new JSExceptionJSRuntime(); await Assert.ThrowsAsync(() => jsRuntime2.LoadModule("./mock.js", "test")); + + var jsRuntime3 = new JSDisconnectedExceptionJSRuntime(); + Assert.NotNull(jsRuntime3.LoadModule("./mock.js", "test")); + + var jsRuntime4 = new ObjectDisposedExceptionJSRuntime(); + Assert.NotNull(jsRuntime4.LoadModule("./mock.js", "test")); } [Fact] @@ -119,4 +125,30 @@ class JSExceptionJSRuntime : IJSRuntime throw new JSException("test-js-exception"); } } + + class JSDisconnectedExceptionJSRuntime : IJSRuntime + { + public ValueTask InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, object?[]? args) + { + throw new JSDisconnectedException("test-js-exception"); + } + + public ValueTask InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, CancellationToken cancellationToken, object?[]? args) + { + throw new JSDisconnectedException("test-js-exception"); + } + } + + class ObjectDisposedExceptionJSRuntime : IJSRuntime + { + public ValueTask InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, object?[]? args) + { + throw new ObjectDisposedException("test-js-exception"); + } + + public ValueTask InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, CancellationToken cancellationToken, object?[]? args) + { + throw new ObjectDisposedException("test-js-exception"); + } + } }