Hello, I'm moving from ASP.net Blazor standard Identity UI to a Radzen-based set of pages. (Using ASP.net 8).
I have a problem with the Login page.
My code is as follows:
App.razor
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<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="BlazId.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
<HeadOutlet @rendermode="@InteractiveServer" />
</head>
<Routes @rendermode="@InteractiveServer" />
<script src="_framework/blazor.web.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
</body>
</html>
In the file SideMenu.razor the following line calls the login page:
<RadzenPanelMenu>
<AuthorizeView>
<Authorized>
</Authorized>
<NotAuthorized>
<RadzenPanelMenuItem Text="Login" Icon="login" Path="Account/Login2"></RadzenPanelMenuItem>
</NotAuthorized>
</AuthorizeView>
</RadzenPanelMenu>
The Login2.razor page is the following, but it's totally irrelevant for the issue I have. For sake of simplicity, I'll bypass it in my example here
@page "/Account/Login2"
@using System.ComponentModel.DataAnnotations
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Identity
@using BlazId.Data
@using Account
@inject SignInManager<MyUser> SignInManager
@inject ILogger<Login2> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
<RadzenCard class="rz-my-12 rz-mx-auto rz-p-4 rz-p-md-12" style="max-width: 600px;">
<RadzenTemplateForm Data=@Input Method="post">
@* <AntiforgeryToken /> *@
<RadzenLogin AllowRegister="true" AllowResetPassword="true" Username=@userName Password=@password
AllowRememberMe="true" RememberMe="@rememberMe"
Login=@(args => OnLogin(args, "Login with default values"))
ResetPassword=@(args => OnResetPassword(args, "Login with default values"))
Register=@(args => OnRegister("Login with default values")) />
</RadzenTemplateForm>
</RadzenCard>
@code {
string userName = "user@domain.com";
string password = "Welcome1";
bool rememberMe = true;
async void Submit(InputModel args)
await LoginUser(args);
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);
public async Task OnLogin(LoginArgs args, string name)
// console.Log($"{name} -> Username: {args.Username}, password: {args.Password}, remember me: {args.RememberMe}");
var result = await SignInManager.PasswordSignInAsync(args.Username, args.Password, args.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
Logger.LogInformation("User logged in.");
// RedirectManager.RedirectTo(ReturnUrl);
void OnRegister(string name)
// console.Log($"{name} -> Register");
void OnResetPassword(string value, string name)
// console.Log($"{name} -> ResetPassword for user: {value}");
[SupplyParameterFromForm]
private InputModel Input { get; set; } = new();
[SupplyParameterFromQuery]
private string? ReturnUrl { get; set; }
[SupplyParameterFromQuery]
private string? RedirectUrl { get; set; }
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
public async Task LoginUser(InputModel model)
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await SignInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
Logger.LogInformation("User logged in.");
// RedirectManager.RedirectTo(ReturnUrl);
else if (result.RequiresTwoFactor)
// RedirectManager.RedirectTo(
// "Account/LoginWith2fa",
// new() { ["returnUrl"] = ReturnUrl, ["rememberMe"] = Input.RememberMe });
else if (result.IsLockedOut)
Logger.LogWarning("User account locked out.");
// RedirectManager.RedirectTo("Account/Lockout");
// errorMessage = "Error: Invalid login attempt.";
public sealed class InputModel
[Required]
[EmailAddress]
public string Email { get; set; } = "";
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = "";
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
The Login2.razor page refers to the follwing _imports.razor file
@using BlazId.Components.Account.Shared
@layout AccountLayout
The big issue comes in the AccountLayout.razor file:
@inherits LayoutComponentBase
@layout BlazId.Components.Layout.MainLayout
@inject NavigationManager NavigationManager
@if (HttpContext is null)
<p>Loading...</p>
<p>LOADED @HttpContext.ToString();</p>
@* @Body *@
@code {
[CascadingParameter]
public HttpContext? HttpContext { get; set; } = default!;
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);
Here I intentionally commented out the @Body just to avoid any overhead from the Layout2.razor content, because the bad behavior is the same:
It continues to reload the page, once with a HttpContext set to null and once with HttpContext set to the proper value. It continues to flash between the two situations indefinitely. If I stop the page using the browser's 'X' (stop) button, sometimes it stops on "Loading...", sometimes it stops on the correct page. When it stops in the correct side, I can properly login and the cookies are properly set.
If in the App.razor page, I change
<HeadOutlet @rendermode="@InteractiveServer" />
<Routes @rendermode="@InteractiveServer" />
<HeadOutlet />
<Routes />
this part work properly, but (as you could imagine) the modal DialogService like DialogService.Alert(...) don't work any more.
How can I have both modal Dialogs AND proper Login page loaded correctly ?
Another things you can try:
Replace RadzenTemplateForm with EditForm and see if this makes a difference.
Avoid setting @rendermode at Routes. Set it to <RadzenComponent /> which is in your layout instead as per our getting started instructions. I am not 100% sure that accessing HttpContext works in interactive rendering modes.
In any case I would start from a working configuration and make changes step by step to see what breaks the implementation.
Hi @mpolazzo
It may be right about HttpContext not working in InteractiveServer mode.
My project created from scratch in Visual Studio 2022 has the following code in App.razor -
@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
? null
: InteractiveServer;
All my "Login" routes begin "/Account".
As already mentioned above, I would strongly recommend creating a fresh project and using the generated code as a learning curve / starting point.
Many regards
Thanks for your answer.
I tried this, the effect is that now it's only flashing (very quickly) "Loading...". The other Login page is not shown alternatively. (
).
I'll try further... thanks.
@korchev Thanks for your answer.
Mine was a clean new application and I isolated the cause of breakage in
<HeadOutlet @rendermode="@InteractiveServer" />
<Routes @rendermode="@InteractiveServer" />
instead of the standard
<HeadOutlet />
<Routes />
I changed it back (without InteractiveServer) and added it to <RadzenComponent /> in MainLayout.razor as follows:
@inject ContextMenuService ContextMenuService
@inject NotificationService NotificationService
<RadzenComponents @rendermode="@InteractiveServer" />
<RadzenLayout style="grid-template-areas: 'rz-sidebar rz-header' 'rz-sidebar rz-body';">
<RadzenHeader>
Now, Login works properly (no flashing with "Loading..."), but the Dialog boxes don't work any more (original reason why I had to set InteractiveServer in App.razor).
Hi @Paul_Ruston finally it worked!!!
I used your @code snippet (that I also had in my App.razor), but instead of using InteractiveServer I had to use RenderModeForPage in the declarations.
Finally, App.razor is as follows:
<html lang="en" data-bs-theme="light">
<HeadOutlet @rendermode="@RenderModeForPage" />
</head>
<Routes @rendermode="@RenderModeForPage" />
</body>
</html>
@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
? null
: InteractiveServer;
Thank you all!!
mpolazzo:
but the Dialog boxes don't work any more (original reason why I had to set InteractiveServer in App.razor).
This would work if used from pages that have @rendermode InteractiveServer. The workaround that you have applied in the end does something similar by changing the "global" render mode depending on the route.
This is case number X where rendering modes make things harder than easier. And there is no end in sight.
I had exactly the same problems but I already solved them.
In App.razor use this in the head:
<HeadOutlet @rendermode="RenderModeForPage" />
then use this in the body:
<Routes @rendermode="RenderModeForPage" />
then in the code:
@code {
** [CascadingParameter]**
** private HttpContext HttpContext { get; set; } = default!;**
** private IComponentRenderMode RenderModeForPage => (HttpContext.Request.Path.StartsWithSegments("/Account") &&**
** !HttpContext.Request.Path.StartsWithSegments("/Account/Manage"))**
** ? null**
** : InteractiveServer;**
in the ManageLayout.razor use @layout MainLayout instead of @layout AccountLayout
then @inject IHttpContextAccessor ctxAccessor
and use:
** @Body**
stop using these 3 classes in all InteractiveServer Mode components:
IdentityUserAccessor
IdentityRedirectManager
IdentityRevalidatingAuthenticationStateProvider
Good luck