Blazor Server ↔ JavaScript Toast Library: Persisting Alerts Across Navigation
0 reputation · 03 Oct 2023, 08:32 UTC
0 reputation · 03 Oct 2023, 08:32 UTC
The goal is to deliver useful, non‑intrusive toast notifications in a Blazor Server application while avoiding browser notification pop‑ups. Developers typically call a JavaScript toast library (e.g., Toastr, SweetAlert) via JS interop, exposing a C# service that queues messages and triggers a single JS function to display them. The challenge is that the service is scoped to the circuit; after a reconnect or navigation, queued alerts can be lost, and the JS interop object may be recreated, causing duplicate or missing toasts.
Key constraints include preserving alert state across circuit reconnects, preventing repeated notifications, and ensuring that “silent” or “info” styled toasts do not trigger native browser notification pop‑ups. The current documentation does not prescribe a persistence strategy or JS interop lifecycle.
What unresolved decisions remain?
Blazor Server circuits are stateful. A scoped C# service lives for the lifetime of the circuit and survives in-app navigation, but it is lost on circuit disconnect, browser refresh, or tab close. That is confirmed behavior.
Confirmed fact: Scoped service state is not available after a reconnect or hard refresh. Queued alerts held only in memory will be lost.
Likely explanation: If you need alerts to survive a reconnect, the state must be moved out of the circuit. Browser-side storage gives immediate re-hydration on reconnect without server round-trip; a server-side per-user store gives durability across devices but adds latency.
Steps needed for this case:
Missing diagnostic detail that changes the recommendation: Do alerts need to survive a full browser refresh, or only a temporary circuit reconnect? Refresh requires durable storage; reconnect can be handled with a short-lived re-hydrate from browser storage.
Confirmed fact: JS interop objects are recreated with the component. Calling the same toast library repeatedly without de-duplication causes duplicates.
Likely explanation: The JavaScript toast library should be initialized once per page load as a global module, and the C# service should only invoke a thin show function.
Steps needed:
Confirmed fact: Native browser notification pop-ups are triggered by the Web Notifications API, not by DOM-based toast libraries such as Toastr or SweetAlert.
Likely explanation: Silent or info styled toasts remain in-page as long as the library is configured for in-DOM rendering and no call to Notification.requestPermission / new Notification is made.
Steps needed:
Assumption: Blazor Server 8+ with standard JS interop. Uncertainty remains around exact reconnect timing for OnInitializedAsync calls; avoid JS interop during early lifecycle until the circuit is established.
Use comments to ask for clarification. Post a solution as an answer.
4,180 reputation · 03 Oct 2023, 17:02 UTC
When you expose the toast library as a global property on window (e.g., window.showToast = (msg, type) => { ... }), any scoped C# ToastService can call it via IJSRuntime.InvokeVoidAsync without tying the toast to a component lifecycle. This keeps the toast visible even after a circuit reconnect because the JS object lives on the page, not the component. Remember to release any DotNetObjectReference you create in Dispose to avoid memory leaks on the SignalR circuit.