I'm upgrading my Blazor application from .NET 7 to .NET 8 and adding Login/Logout functionality using the Identity code from the sample Blazor Web App project in Visual Studio. My problem is that I want to set the entire application to Interactive Server rendering without having to put a rendermode
directive on each page. So I added <Routes @rendermode="InteractiveServer" />
to my App.razor
file. The problem is that the Login page gets stuck in an endless loop of refreshing itself because of Interactive Server render mode.
App.razor
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><base href="/" /><link rel="stylesheet" href="bootstrap/bootstrap.min.css" /><link rel="stylesheet" href="app.css" /><link rel="stylesheet" href="BlazorWebApp.styles.css" /><link rel="icon" type="image/png" href="favicon.png" /><HeadOutlet @rendermode="InteractiveServer" /></head><body><Routes @rendermode="InteractiveServer" /><script src="_framework/blazor.web.js"></script></body></html>
Routes.razor
@using BlazorWebApp.Components.Account.Shared<Router AppAssembly="typeof(Program).Assembly"><Found Context="routeData"><AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"><NotAuthorized><RedirectToLogin /></NotAuthorized></AuthorizeRouteView><FocusOnNavigate RouteData="routeData" Selector="h1" /></Found></Router>
This is the relevant code from the Login page that is part of the Blazor Web App project. The Login page refreshes itself when it's in Interactive Server mode (based on the code in the layout), but since the Render Mode is at the application level, the page is still in Interactive Server mode when it gets refreshed. So it refreshes endlessly.
AccountLayout.razor
[CascadingParameter]private HttpContext HttpContext { get; set; }protected override void OnParametersSet(){ if (HttpContext is null) { // If this code runs, we're currently rendering in interactive mode, so there is no HttpContext. // The identity pages need to set cookies, so they require an HttpContext. To achieve this we // must transition back from interactive mode to a server-rendered page. NavigationManager.Refresh(forceReload: true); }}
Login.razor
[CascadingParameter]private HttpContext HttpContext { get; set; }protected override async Task OnInitializedAsync(){ if (HttpMethods.IsGet(HttpContext.Request.Method)) { // Clear the existing external cookie to ensure a clean login process await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); }}
Is there a way to get my Login page to function correctly without having to take out the @rendermode
attribute on the Routes
element and put a @rendermode
directive in every page other than the Login page?