Blazor SignalR 调用错误的 JSRuntime
Blazor SignalR Call Wrong JSRuntime
我创建事件映射座位预订并使用 SignalR 创建实时座位更新状态视图
我的 BroadcastHub
public class BroadcastHub : Hub
{
public async Task AddToGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
public async Task RemoveFromGroup(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
}
public async Task SeatUpdate(long SectinId, string groupName, long SeatId, SeatStatus seatStatus)
{
await Clients.OthersInGroup(groupName).SendAsync("ReceiveSeatUpdate", SectinId, SeatId, seatStatus);
}
}
组件
<div class="col-md-12 mb-3">
@((MarkupString)@SectionData.Salon.SalonMap)
</div>
...Seat Selection Murkup....
@code {
private HubConnection hubConnection;
public bool IsConnected => hubConnection.State == HubConnectionState.Connected;
Task SeatUpdate(long SectinId, string EventId, long SeatId, SeatStatus seatStatus) => hubConnection.SendAsync("SeatUpdate", SectinId, EventId, SeatId, seatStatus);
protected override async Task OnInitializedAsync()
{
SectionData.OnChange += StateHasChanged;
SectionData.Salon = await DataService.GetSalon();
action = GetSection;
foreach (var item in salon.Sections)
{
SectionData.Salon.SalonMap =salon.SalonMap.Replace(item.Action,$"onclick='app.GetSectionCallerJS({item.Id})'");
}
#region Hub
hubConnection = new HubConnectionBuilder().WithUrl(NavigationManager.ToAbsoluteUri("/broadcastHub")).Build();
hubConnection.On("ReceiveSeatUpdate", async (long SectinId, long SeatId, SeatStatus seatStatus) =>
{
if (SectionData.Section.Id == SectinId)
{
var Seat = SectionData.Section.Seats.Values.Where(x => x.Id == SeatId).FirstOrDefault();
Seat.SeatStatus = seatStatus;
}
StateHasChanged();
});
await hubConnection.StartAsync();
await hubConnection.SendAsync("AddToGroup", EventSansUniqueId);
#endregion Hub
}
#region GetSection
private static Action<long> action;
private void GetSection(long SectionId)
{
var section= salon.Sections.Where(x => x.Id == SectionId).FirstOrDefault();
SectionData.SetSection(section);
SectionData.Section.Seats = DataService.GetSection(SectionId);
StateHasChanged();
}
[JSInvokable]
public static void GetSectionCaller(long SectionId)
{
action.Invoke(SectionId);
}
#endregion GetSection
public void Dispose()
{
SectionData.OnChange -= StateHasChanged;
if (IsConnected) hubConnection.SendAsync("RemoveFromGroup", EventSansUniqueId);
}
}
JavaScript 是
window.app = {
GetSectionCallerJS: (id) => {
DotNet.invokeMethodAsync('KishApp.TRMS.Salon', 'GetSectionCaller', id);
}
};
问题是当集线器注册第二次、第三次……时 DotNet.invokeMethodAsync
调用上次注册的页面,而不是实际调用该方法并导致错误页面更新的页面
感谢@MisterMango 我发现问题 GetSectionCaller
是一个静态方法,我必须在每次页面初始时创建新的 DotNetObjectReference
所以
DotNetObjectReference<Salon> ObjectReference;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
ObjectReference = DotNetObjectReference.Create<Salon>(this);
await JSRuntime.InvokeVoidAsync("app.setObjectReference", ObjectReference);
}
}
[JSInvokable("GetSectionCaller")]
public void GetSectionCaller(long SectionId)
{
GetSection(SectionId);
}
JavaScript
window.app = {
GetSectionCallerJS: (id) => {
dotNetObject.invokeMethodAsync('GetSectionCaller', id);
},
setObjectReference: (ObjectReference) => {
this.dotNetObject = ObjectReference;
}};
我创建事件映射座位预订并使用 SignalR 创建实时座位更新状态视图
我的 BroadcastHub
public class BroadcastHub : Hub
{
public async Task AddToGroup(string groupName)
{
await Groups.AddToGroupAsync(Context.ConnectionId, groupName);
}
public async Task RemoveFromGroup(string groupName)
{
await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName);
}
public async Task SeatUpdate(long SectinId, string groupName, long SeatId, SeatStatus seatStatus)
{
await Clients.OthersInGroup(groupName).SendAsync("ReceiveSeatUpdate", SectinId, SeatId, seatStatus);
}
}
组件
<div class="col-md-12 mb-3">
@((MarkupString)@SectionData.Salon.SalonMap)
</div>
...Seat Selection Murkup....
@code {
private HubConnection hubConnection;
public bool IsConnected => hubConnection.State == HubConnectionState.Connected;
Task SeatUpdate(long SectinId, string EventId, long SeatId, SeatStatus seatStatus) => hubConnection.SendAsync("SeatUpdate", SectinId, EventId, SeatId, seatStatus);
protected override async Task OnInitializedAsync()
{
SectionData.OnChange += StateHasChanged;
SectionData.Salon = await DataService.GetSalon();
action = GetSection;
foreach (var item in salon.Sections)
{
SectionData.Salon.SalonMap =salon.SalonMap.Replace(item.Action,$"onclick='app.GetSectionCallerJS({item.Id})'");
}
#region Hub
hubConnection = new HubConnectionBuilder().WithUrl(NavigationManager.ToAbsoluteUri("/broadcastHub")).Build();
hubConnection.On("ReceiveSeatUpdate", async (long SectinId, long SeatId, SeatStatus seatStatus) =>
{
if (SectionData.Section.Id == SectinId)
{
var Seat = SectionData.Section.Seats.Values.Where(x => x.Id == SeatId).FirstOrDefault();
Seat.SeatStatus = seatStatus;
}
StateHasChanged();
});
await hubConnection.StartAsync();
await hubConnection.SendAsync("AddToGroup", EventSansUniqueId);
#endregion Hub
}
#region GetSection
private static Action<long> action;
private void GetSection(long SectionId)
{
var section= salon.Sections.Where(x => x.Id == SectionId).FirstOrDefault();
SectionData.SetSection(section);
SectionData.Section.Seats = DataService.GetSection(SectionId);
StateHasChanged();
}
[JSInvokable]
public static void GetSectionCaller(long SectionId)
{
action.Invoke(SectionId);
}
#endregion GetSection
public void Dispose()
{
SectionData.OnChange -= StateHasChanged;
if (IsConnected) hubConnection.SendAsync("RemoveFromGroup", EventSansUniqueId);
}
}
JavaScript 是
window.app = {
GetSectionCallerJS: (id) => {
DotNet.invokeMethodAsync('KishApp.TRMS.Salon', 'GetSectionCaller', id);
}
};
问题是当集线器注册第二次、第三次……时 DotNet.invokeMethodAsync
调用上次注册的页面,而不是实际调用该方法并导致错误页面更新的页面
感谢@MisterMango 我发现问题 GetSectionCaller
是一个静态方法,我必须在每次页面初始时创建新的 DotNetObjectReference
所以
DotNetObjectReference<Salon> ObjectReference;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if (firstRender)
{
ObjectReference = DotNetObjectReference.Create<Salon>(this);
await JSRuntime.InvokeVoidAsync("app.setObjectReference", ObjectReference);
}
}
[JSInvokable("GetSectionCaller")]
public void GetSectionCaller(long SectionId)
{
GetSection(SectionId);
}
JavaScript
window.app = {
GetSectionCallerJS: (id) => {
dotNetObject.invokeMethodAsync('GetSectionCaller', id);
},
setObjectReference: (ObjectReference) => {
this.dotNetObject = ObjectReference;
}};