@using JSMR.UI.Blazor.Services @using Microsoft.AspNetCore.Components.Routing @inject SessionState Session @inject NavigationManager Navigation @if (!_ready) {

Loading...

} else { @ChildContent } @code { [Parameter] public RenderFragment? ChildContent { get; set; } private bool _ready; // Add any routes you want public here. // Use absolute-path form (leading slash). private static readonly HashSet _allowAnonymous = new(StringComparer.OrdinalIgnoreCase) { "/login", "/login/", // optional }; protected override async Task OnInitializedAsync() { Navigation.LocationChanged += OnLocationChanged; // One-time refresh at app start await Session.RefreshAsync(); _ready = true; await EnforceAsync(); } private async void OnLocationChanged(object? sender, LocationChangedEventArgs e) { // If your Session can change based on navigation/cookies, you *may* refresh here, // but avoid doing it on every navigation unless necessary. // await Session.RefreshAsync(); await EnforceAsync(); } private Task EnforceAsync() { if (!_ready) return Task.CompletedTask; var path = "/" + Navigation.ToBaseRelativePath(Navigation.Uri); var qIndex = path.IndexOf('?', StringComparison.Ordinal); if (qIndex >= 0) path = path[..qIndex]; // allow anonymous routes if (_allowAnonymous.Contains(path)) return Task.CompletedTask; if (!Session.IsAuthenticated) { var returnUrl = Uri.EscapeDataString(Navigation.Uri); Navigation.NavigateTo($"/login?returnUrl={returnUrl}", forceLoad: false); } return Task.CompletedTask; } public void Dispose() => Navigation.LocationChanged -= OnLocationChanged; }