The framework I am using is .Net 8 Blazor Web App. And the authentication is based on Microsoft.AspNetCore.Identity.EntityFramework .
I want the ValidationMessage dynamic update but HttpContext/SignInManager/UserManager are not supported by rendermode InteractiveServer.
Now I try to send a Json to a controller to implement this.
I implemented the register page by this successfully (without auto login in).
However, when I try the same way with login page, I meet a strange problem that it can not login.
Here is the code of razor page:
@inject IHttpClientFactory _HttpClientFactory@inject IStringLocalizer<Login> _Localizer<EditForm Model="_Input" method="post" OnValidSubmit="LoginUser" FormName="login" Enhance class="Flex"><DataAnnotationsValidator /><div id="SubmitDiv" class="FlexAll"><InputText @bind-Value="_Input.Email" class="ant-input SubmitContentInput" autocomplete="username" aria-required="true" placeholder="@_Localizer["ErrorMessageUserNameRequire"]" /><ValidationMessage For="() => _Input.Email" class="ant-form-item-explain-error" /><InputText @bind-Value="_Input.Password" type="password" class="ant-input SubmitContentInput" autocomplete="current-password" aria-required="true" placeholder="@_Localizer["ErrorMessagePasswordRequire"]" /><ValidationMessage For="() => _Input.Password" class="ant-form-item-explain-error" /></div> <button type="submit" class="ant-btn ant-btn-primary Flex">@_Localizer["Login"]</button></div></EditForm>[SupplyParameterFromForm]private LoginModel _Input { get; set; } = new(); public async Task LoginUser() { var httpClient = _HttpClientFactory.CreateClient(); var httpResponseMessage = await httpClient.PostAsJsonAsync<LoginModel>($"{_NavigationManager.BaseUri}Login/Login", this._Input); if (httpResponseMessage.IsSuccessStatusCode) { var result = await httpResponseMessage.Content.ReadFromJsonAsync<LoginResultModel>(); if (result is { }) { switch (result.LoginResultType) { case LoginResultModel.LoginResultTypeEnum.Success: { _NavigationManager.NavigateTo("/"); return; } } } else { await _Message.Error(_Localizer["UnableToLogInNormally"].Value); } } }
And here is the controller:
[Microsoft.AspNetCore.Mvc.Route("[controller]/[action]")]public class LoginController:Controller{ readonly SignInManager<ApplicationUser> _SignInManager; readonly ILogger<Login> _Logger; public LoginController(SignInManager<ApplicationUser> signInManager, ILogger<Login> logger) { _SignInManager = signInManager; _Logger = logger; } [HttpPost] [Produces("application/json")] public async Task<ActionResult<LoginResultModel>> Login([FromBody] LoginModel login) { // This doesn't count login failures towards account lockout // To enable password failures to trigger account lockout, set lockoutOnFailure: true LoginResultModel _loginResult = new LoginResultModel(); var result = await _SignInManager.PasswordSignInAsync(login.Email, login.Password, login.RememberMe, lockoutOnFailure: false); if (result. Succeeded) { _Logger.LogInformation("User logged in."); _loginResult.LoginResultType = LoginResultModel.LoginResultTypeEnum.Success; return _loginResult; } else if (result.RequiresTwoFactor) { _loginResult.LoginResultType = LoginResultModel.LoginResultTypeEnum.RequiresTwoFactor; _loginResult.QueryParameter = new() { ["rememberMe"] = login.RememberMe }; return _loginResult; } else if (result.IsLockedOut) { _loginResult.LoginResultType = LoginResultModel.LoginResultTypeEnum.LockedOut; return _loginResult; } else { _loginResult.LoginResultType = LoginResultModel.LoginResultTypeEnum.InvalidLoginAttempt; return _loginResult; } }
I tried to get the result of SignInManager.PasswordSignInAsync in the controller by break point and it is logged in successfully.
However, in AutherizeView it still is the view that not logged in:
<AuthorizeView><Authorized><div class="page"><div class="sidebar"><NavMenu /></div><main><div class="top-row px-4"><a href="https://learn.microsoft.com/aspnet/core/" target="_blank">@_Localizer["Test"]</a></div><article class="content px-4"> @Body</article></main></div></Authorized><NotAuthorized><Login></Login></NotAuthorized></AuthorizeView>
What's wrong with my code?