You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8 Blazor两种场景下导航与HttpContext异常问题求助

问题1:数据库保存后调用NavigationManager重定向报错

原因

Blazor静态SSR模式下,表单提交为服务器端回发处理,NavigationManager.NavigateTo是客户端导航API,在服务器端执行时无客户端上下文,导致报错;同时同步的SaveChanges不符合异步编程规范,易造成线程阻塞。

解决方案

改用服务器端重定向方式,让表单提交方法返回IActionResult,通过RedirectToPage实现重定向,同时使用异步版本的数据库保存方法。

修改后的代码

@page "/UpsertGame"
@using BlazorAppAuth.Models;
@using BlazorAppAuth.Data;
@inject DataContext _dataContext;
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<h3>AddNewGames</h3>
<EditForm Model="videoGame" OnSubmit="Submit" FormName="Game">
    <div class="row">
        <div class="col-md-3">
            <label>Title</label>
            <InputText @bind-Value="videoGame.Title" class="form-control form-control-sm"></InputText>
        </div>
        <div class="col-md-3">
            <label>Publisher</label>
            <InputText @bind-Value="videoGame.Publisher" class="form-control form-control-sm"></InputText>
        </div>
        <div class="col-md-3">
            <label>Released Year</label>
            <InputNumber @bind-Value="videoGame.ReleasedYear" class="form-control form-control-sm"></InputNumber>
        </div>
        <div class="col-md-3">
            <input type="submit" class="btn btn-sm btn-dark" name="Submit" />
        </div>
    </div>
</EditForm>

@code {
    [SupplyParameterFromForm]
    private VideoGame videoGame { get; set; } = new();

    public async Task<IActionResult> Submit()
    {
        try
        {
            _dataContext.VideoGame.Add(videoGame);
            var result = await _dataContext.SaveChangesAsync();
            if (result == 1)
                return RedirectToPage("/UpsertGame");
            
            // 保存失败返回当前页,可添加错误提示
            return Page();
        }
        catch (Exception ex)
        {
            // 处理异常,比如记录日志或添加ModelState错误
            ModelState.AddModelError(string.Empty, "保存失败,请重试");
            return Page();
        }
    }
}

问题2:登录场景HttpContext与NavigationManager的矛盾

原因

  1. InteractiveServer模式下HttpContext为null:该模式下组件后续交互通过SignalR连接执行,仅初始渲染阶段有HttpContext,后续操作无法访问。
  2. 静态SSR模式下Headers只读错误:组件渲染过程中响应已开始输出,此时调用SignInAsync需要修改响应头设置Cookie,导致冲突。

解决方案

将登录逻辑移至服务器端的Razor Page或API控制器,避免在Blazor组件中直接操作HttpContext或修改响应头。

步骤1:创建登录处理的Razor Page

Login.cshtml.cs

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Claims;

namespace BlazorAppAuth.Pages;

[AllowAnonymous]
public class LoginModel : PageModel
{
    [BindProperty]
    public UserCredentials UserCredentials { get; set; } = new();

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
            return Page();

        if (UserCredentials.Username == "Ankesh" && UserCredentials.Password == "ank")
        {
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, UserCredentials.Username)
            };
            var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            var principal = new ClaimsPrincipal(identity);
            
            await HttpContext.SignInAsync(principal);
            return RedirectToPage("/");
        }

        ModelState.AddModelError(string.Empty, "用户名或密码错误");
        return Page();
    }

    public class UserCredentials
    {
        public string Username { get; set; } = string.Empty;
        public string Password { get; set; } = string.Empty;
    }
}

Login.cshtml

@page "/login"
@model BlazorAppAuth.Pages.LoginModel

<h3>登录</h3>
<div class="row">
    <div class="col-md-4">
        <form method="post">
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="mb-3">
                <label asp-for="UserCredentials.Username" class="form-label"></label>
                <input asp-for="UserCredentials.Username" class="form-control" />
                <span asp-validation-for="UserCredentials.Username" class="text-danger"></span>
            </div>
            <div class="mb-3">
                <label asp-for="UserCredentials.Password" class="form-label"></label>
                <input asp-for="UserCredentials.Password" type="password" class="form-control" />
                <span asp-validation-for="UserCredentials.Password" class="text-danger"></span>
            </div>
            <button type="submit" class="btn btn-dark">登录</button>
        </form>
    </div>
</div>

步骤2:Blazor组件中跳转至登录页(可选)

如果需要在Blazor组件中触发登录跳转,直接使用NavigationManager即可(静态SSR或InteractiveServer模式下均有效):

@inject NavigationManager NavigationManager

<button class="btn btn-link" @onclick="() => NavigationManager.NavigateTo("/login")">
    登录
</button>

内容的提问来源于stack exchange,提问作者Ankesh kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:30:55