Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.3.1-beta24</Version>
<Version>9.3.1-beta25</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
});
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/BootstrapBlazor/Extensions/JSModuleExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static async Task<JSModule> LoadModule(this IJSRuntime jsRuntime, string
{
jSObjectReference = await jsRuntime.InvokeAsync<IJSObjectReference>(identifier: "import", fileName);
}
catch (JSDisconnectedException) { }
catch (JSException)
{
#if DEBUG
Expand All @@ -58,6 +59,7 @@ public static async Task<JSModule> LoadModule(this IJSRuntime jsRuntime, string
#endif
}
catch (OperationCanceledException) { }
catch (ObjectDisposedException) { }
return new JSModule(jSObjectReference);
}

Expand Down
16 changes: 7 additions & 9 deletions src/BootstrapBlazor/Services/WebClientService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,17 @@ public async Task<ClientInfo> 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 地址信息
Expand Down
20 changes: 9 additions & 11 deletions src/BootstrapBlazor/wwwroot/modules/client.js
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/BootstrapBlazor/wwwroot/modules/hub.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 () => {
Expand Down
32 changes: 32 additions & 0 deletions test/UnitTest/Extensions/JSModuleExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ public async Task LoadModule_Ok()

var jsRuntime2 = new JSExceptionJSRuntime();
await Assert.ThrowsAsync<JSException>(() => 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]
Expand Down Expand Up @@ -119,4 +125,30 @@ class JSExceptionJSRuntime : IJSRuntime
throw new JSException("test-js-exception");
}
}

class JSDisconnectedExceptionJSRuntime : IJSRuntime
{
public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, object?[]? args)
{
throw new JSDisconnectedException("test-js-exception");
}

public ValueTask<TValue> 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<TValue> InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, object?[]? args)
{
throw new ObjectDisposedException("test-js-exception");
}

public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties)] TValue>(string identifier, CancellationToken cancellationToken, object?[]? args)
{
throw new ObjectDisposedException("test-js-exception");
}
}
}