将我的 Blazor .Net6 项目迁移到 .Net8 后,我的 cookie 管理被破坏,并且我找不到解决方法。
由于主题化和避免 FOUC,我需要在首次渲染之前访问 HTTP 请求中的 cookie。我天真地尝试将 cookie 存储在注入根
ThemeService
组件中的作用域 App
中,因为只有根才能将 HttpContext
作为 CascadingParameter
访问。但是,注入到任何其他页面或组件中的相同 ThemeService
只会实例化 second 作用域服务...顺便说一句,我正在使用 RenderMode.InteractiveServer,并在 HeadOutlet/Router 级别全局禁用预渲染。
我的理论是,根
App
组件的 DI 范围基于原始 HTTP 请求,而所有其他组件 DI 范围都基于稍后才建立的 Blazor SignalR 连接。
所以我的问题是:在我的组件渲染之前,如何将 cookie 数据从第一个作用域传递到另一个作用域?
我唯一能想到的是创建一个单例服务,在其中存储 IP/cookie 或类似的字典,从根
App
组件插入它,然后以某种方式从 SignalR 获取 IP 并在辛格尔顿。这可能/可行吗?我真的很感激任何有关此问题的帮助或意见,它看起来很基本,但我很困惑。
提前致谢!
您可以尝试:
@page "/"
@inject StateContainer StateContainer
@inject PersistentComponentState ApplicationState
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
CookieVal:@data
@code{
[CascadingParameter]
public HttpContext? httpContext { get; set; }
private string data;
private PersistingComponentStateSubscription persistingSubscription;
protected override void OnInitialized()
{
StateContainer.OnChange += StateHasChanged;
if (httpContext is not null)
{
var existTargetCookie = httpContext.Request.Cookies.TryGetValue("CookieKey", out data);
}
else
{
if(ApplicationState.TryTakeFromJson<string>(
"Cookie", out data))
{
StateContainer.Property = data;
}
else
{
data = StateContainer.Property;
}
}
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistData);
}
private Task PersistData()
{
ApplicationState.PersistAsJson("Cookie", data);
return Task.CompletedTask;
}
public void Dispose()
{
persistingSubscription.Dispose();
StateContainer.OnChange -= StateHasChanged;
}
}
public class StateContainer
{
private string? savedString;
public string Property
{
get => savedString ?? string.Empty;
set
{
savedString = value;
NotifyStateChanged();
}
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
结果: