Blazor Server如何获取窗口会话唯一ID,避免触发源窗口收到Toast提示?
Blazor Server 区分同一用户不同浏览器窗口的实现方案
- 利用sessionStorage存储窗口唯一ID:sessionStorage是浏览器窗口级别的存储,每个窗口独立,关闭窗口后自动清除,完美匹配需求。
- 客户端生成并维护窗口ID:通过JSInterop在客户端初始化时生成UUID作为窗口ID,存入sessionStorage,确保每个窗口有唯一标识。
- 服务端传递过滤标识:发送Toast事件时携带触发窗口的originationID,其他客户端收到后对比自身窗口ID,匹配则忽略提示。
具体实现步骤
1. 客户端JS逻辑(wwwroot/js/windowId.js)
window.getWindowId = () => { let windowId = sessionStorage.getItem('BlazorWindowId'); if (!windowId) { // 生成UUID作为唯一窗口ID windowId = crypto.randomUUID(); sessionStorage.setItem('BlazorWindowId', windowId); } return windowId; };
2. Blazor组件中获取窗口ID
在需要使用窗口ID的组件(或全局服务)中,通过JSInterop获取并存储:
@inject IJSRuntime JS @inject IToastEventService ToastEventService // 自定义的事件服务 private string _currentWindowId; protected override async Task OnInitializedAsync() { // 获取当前窗口ID _currentWindowId = await JS.InvokeAsync<string>("getWindowId"); // 订阅Toast事件,处理过滤逻辑 ToastEventService.OnToastReceived += HandleToastReceived; } private void HandleToastReceived(ToastNotification toast) { // 如果触发窗口ID与当前窗口ID一致,忽略提示 if (toast.OriginationId == _currentWindowId) return; // 显示Toast提示逻辑 ShowToast(toast); } public void Dispose() { ToastEventService.OnToastReceived -= HandleToastReceived; }
3. 发送Toast事件时携带originationID
当用户更新资源触发事件时,将当前窗口ID作为originationID传入:
public class ToastEventService { public event Action<ToastNotification> OnToastReceived; public void SendToast(ToastNotification toast) { OnToastReceived?.Invoke(toast); } } // 资源更新时触发 public async Task UpdateResource() { // 业务逻辑... // 获取当前窗口ID var originationId = await JS.InvokeAsync<string>("getWindowId"); var toast = new ToastNotification { Message = "资源已更新,是否刷新视图?", OriginationId = originationId, UserId = CurrentUserId // 用于跨用户过滤 }; // 推送事件给所有客户端 ToastEventService.SendToast(toast); }
4. 未登录用户登录后的处理
未登录用户的窗口ID已存储在sessionStorage中,登录后无需重新生成,只需将窗口ID与当前用户ID关联即可。后续推送事件时,即使是登录后的用户,只要窗口ID与originationID不同,仍会收到提示。
替代方案:利用CircuitId
Blazor Server中每个窗口对应一个独立的Circuit,可通过CircuitAccessor获取CircuitId:
@inject Microsoft.AspNetCore.Components.Server.Circuits.ICircuitAccessor CircuitAccessor private string _circuitId; protected override void OnInitialized() { _circuitId = CircuitAccessor.Circuit?.Id; }
但CircuitId会在页面刷新、重连时变化,而sessionStorage的窗口ID仅在窗口关闭时失效,更符合“窗口会话唯一”的需求。
内容的提问来源于stack exchange,提问作者user101289
相关产品推荐
相关产品推荐

