Open
Description
Hi
i create new blazor 8 web app auto render
I want to define a C# timer on the default login page razor
private TimeSpan timeLeft = TimeSpan.FromMinutes(1).Add(TimeSpan.FromSeconds(59));
private System.Timers.Timer? countdownTimer;
private void StartTimer()
{
countdownTimer = new System.Timers.Timer(1000); // 1 second
countdownTimer.Elapsed += (sender, e) =>
{
if (timeLeft.TotalSeconds > 0)
{
timeLeft = timeLeft.Subtract(TimeSpan.FromSeconds(1));
InvokeAsync(StateHasChanged);
}
else
{
countdownTimer?.Stop();
}
};
countdownTimer.Start();
}
But because the page uses SSR (server-side rendering), it doesn't work — when the time decreases, the page doesn't update at all; it basically doesn't work.
When I change the RenderMode to something like interactive server, it works fine.
But then, when I try to sign in, it throws a "headers are read-only, response has already started" error, meaning the page must use SSR.
Login.razor
@page "/admin-pro/account/sign-in"
@layout AuthLayout
@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> userManager
@inject IUserAdminService authAdminService
@inject ILogger<Login> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
<PageTitle>Sign In</PageTitle>
<div class="card p-2 bg-opacity-8" id="form-s">
<!-- Logo -->
<div class="app-brand justify-content-center mt-2">
<span class="app-brand-logo demo">
<img src="/images/main-brand.png" width="350" />
</span>
@* <span class="app-brand-text demo text-heading fw-bold">Aircraft Finder</span> *@
</div>
<!-- /Logo -->
<div class="card-body mt-2">
<EditForm Model="Input" class="login-form mb-3" method="post" OnValidSubmit="LoginUser" FormName="login">
<DataAnnotationsValidator />
<div class="alert alert-solid-danger d-flex align-items-center @visibleError" role="alert">
<i class="mdi mdi-alert-outline me-2"></i>
@errorMessage
</div>
<div class="form-floating form-floating-outline mb-3">
<InputText @bind-Value="Input.Username" type="text" class="form-control" placeholder="Enter your username" autofocus />
<label for="email">Username</label>
<ValidationMessage For="@(() => Input.Username)" />
</div>
<div class="mb-3">
<div class="form-password-toggle">
<div class="input-group input-group-merge">
<div class="form-floating form-floating-outline">
<InputText @bind-Value="Input.Password" type="password" class="form-control" placeholder="Enter your password" />
<label for="password">Password</label>
<ValidationMessage For="@(() => Input.Password)" />
</div>
</div>
</div>
</div>
<div class="mb-3 d-flex justify-content-between">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="remember-me">
<label class="form-check-label" for="remember-me">
Remember me
</label>
</div>
</div>
<div class="mb-3">
<button class="btn btn-primary d-grid w-100" type="submit">Sign In</button>
</div>
</EditForm>
<div class="col-md-8 row m-auto mt-2">
<p class="notice is-md text-right text-2 text-grays-500 mb-4 text-center " data-v-4c79b6d3="">
<span class="fw-bold">@timeLeft.ToString(@"mm\:ss")</span>
until you can request the code again
</p>
</div>
</div>
</div>
@code {
private string? errorMessage;
private string visibleError = "d-none";
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
[SupplyParameterFromForm]
private LoginAdminDTO Input { get; set; } = new();
[SupplyParameterFromQuery]
private string? ReturnUrl { 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);
}
}
public async Task LoginUser()
{
var result = await authAdminService.LoginAsync(Input);
if (result.Status is ResponseStatus.Success)
{
NavigationManager.NavigateTo("/admin-pro");
}
else
{
errorMessage = result.Message;
visibleError = "";
}
}
private TimeSpan timeLeft = TimeSpan.FromMinutes(1).Add(TimeSpan.FromSeconds(59));
private System.Timers.Timer? countdownTimer;
private void StartTimer()
{
countdownTimer = new System.Timers.Timer(1000); // 1 second
countdownTimer.Elapsed += (sender, e) =>
{
if (timeLeft.TotalSeconds > 0)
{
timeLeft = timeLeft.Subtract(TimeSpan.FromSeconds(1));
InvokeAsync(StateHasChanged);
}
else
{
countdownTimer?.Stop();
}
};
countdownTimer.Start();
}
public void Dispose()
{
countdownTimer?.Dispose();
}
}
and
Is it even possible to implement an interactive server or assembly so that I can build anything I want and not run into issues like 'Headers are read only...