На прошлой неделе я работал над проектом .net 8 своего веб-приложения blazor, и все работало нормально. Теперь я вернулся и больше не могу войти. Моя страница входа выдает ошибку.
Логин.razor:
@page "/Account/Login"
@layout EmptyLayout
@attribute [AllowAnonymous]
@using System.ComponentModel.DataAnnotations
@using AVAZicht.Components.Layout
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Identity
@using AVAZicht.Data
@inject SignInManager<ApplicationUser> SignInManager
@inject ILogger<Login> Logger
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager
<PageTitle>Log in</PageTitle>
<div class = "container">
<div class = "row justify-content-md-center align-items-center vh-100">
<div class = "col-lg-4" align = "center">
<img src = "images/ava_logo_transp.png" class = "w-75 mb-3" />
<section class = "p-0">
<StatusMessage Message = "@errorMessage" />
<EditForm Model = "Input" method = "post" OnValidSubmit = "LoginUser" FormName = "login">
<DataAnnotationsValidator />
<ValidationSummary class = "text-danger" role = "alert" />
<div class = "form-floating mb-3">
<InputText @bind-Value = "Input.Email" class = "form-control" autocomplete = "username" aria-required = "true" placeholder = "[email protected]" />
<label for = "email" class = "form-label">Email</label>
<ValidationMessage For = "() => Input.Email" class = "text-danger" />
</div>
<div class = "form-floating mb-3">
<InputText type = "password" @bind-Value = "Input.Password" class = "form-control" autocomplete = "current-password" aria-required = "true" placeholder = "password" />
<label for = "password" class = "form-label">Password</label>
<ValidationMessage For = "() => Input.Password" class = "text-danger" />
</div>
<div class = "checkbox mb-3">
<label class = "form-label">
<InputCheckbox @bind-Value = "Input.RememberMe" class = "darker-border-checkbox form-check-input" />
Ingelogd blijven
</label>
</div>
<div>
<button type = "submit" class = "w-100 btn btn-lg btn-primary">Inloggen</button>
</div>
</EditForm>
</section>
</div>
</div>
</div>
@code {
private string? errorMessage;
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
[SupplyParameterFromForm]
private InputModel 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()
{
// 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");
}
else
{
errorMessage = "Error: Invalid login attempt.";
}
}
private 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; }
}
}
Ошибка, которую я получаю:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
AVAZicht.Components.Account.Pages.Login.HttpContext.get returned null.
Я создал чистый проект Blazor Web App .net 8 с отдельными учетными записями в качестве типа аутентификации, и он работает отлично. Я просмотрел каждую страницу, которую он использует, перейдя на страницу входа в систему.
У кого-нибудь есть советы?





HttpContext доступен только в режиме SSR (статический рендеринг сервера). https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-8.0#ihttpcontextaccessorhttpcontext-in-razor-comComponents-blazor.
App.razor устанавливает глобальный режим рендеринга:
<Routes /> означает «нет интерактивности», для которого будет установлено значение SSR.<Routes @rendermode = "new InteractiveServerRenderMode"/> будет установлено значение «SSR (prerender) + интерактивный сервер»<Routes @rendermode = "new InteractiveServerRenderMode(prerender: false)"/> будет установлен чистый «интерактивный сервер» без SSR.Таким образом, HttpContext доступен только при использовании первого (SSR).
Если вы создадите шаблон с «индивидуальной аутентификацией» и отметите App.razor, вы найдете
...
<Routes @rendermode = "RenderModeForPage" />
...
@code {
[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;
private IComponentRenderMode? RenderModeForPage => HttpContext.Request.Path.StartsWithSegments("/Account")
? null
: InteractiveServer;
}
Он использует «динамический» глобальный режим. Если маршрут страницы — «/account/...», для этого режима рендеринга страницы будет установлено значение null, что соответствует SSR. https://learn.microsoft.com/en-us/aspnet/core/blazor/comComponents/render-modes?view=aspnetcore-8.0#area-folder-of-static-ssr-comComponents
Спасибо, это отлично работает! Какова наилучшая практика в отношении предварительного рендеринга true/false? Когда использовать не использовать предварительный рендер?
@ Джереми. SSR (пререндер) использует «Httpcontext». InteractiveServer использует «websocket». На мой взгляд, WASM загружается медленно, поэтому я рассмотрю возможность использования пререндера для быстрой загрузки некоторых статических страниц. Я предпочитаю отключать предварительный рендеринг при использовании «InteractiveServer», потому что он уже загружается быстро. Но если вашему механизму нужен httpcontext, вы можете рассмотреть возможность использования страницы SSR или, проще говоря, просто создать контроллер API для обработки кодов, связанных с httpcontext.
Официальные документы немного вводят в заблуждение. Они говорят: «... использует HttpContext, чтобы определить, отображается ли компонент на сервере». Однако, как вы отметили, HttpContext определяет только то, является ли компонент интерактивным или SSR! ничего о местонахождении интерактивности нельзя определить из HttpContext.
Я удалил
@rendermode = "new InteractiveServerRenderMode(prerender: false)"из<Routes />и<HeadOutlet />в файле app.razor, и теперь страница входа снова работает. Как это работает? Не могу ли я установить режим рендеринга по умолчанию?