[英]Blazor Server Storing Initial QueryParameters
Problem: Storing startup query strings for the life of the session. These startup query strings are optional parameters ("?mode=run") and do not persist between pages.问题:在 session 的生命周期内存储启动查询字符串。这些启动查询字符串是可选参数(“?mode=run”)并且不会在页面之间持续存在。 I'm having a hard time finding a single entry point to set the
ProtectedSessionStorage
.我很难找到一个入口点来设置
ProtectedSessionStorage
。
1. First I tried a scoped service with dependency injection. 1.首先我尝试了一个带有依赖注入的范围服务。 That works great until the user refreshes the page.
在用户刷新页面之前效果很好。
private RunModeSettings _rms = new RunModeSettings();
private readonly ProtectedSessionStorage _protectedSessionStore;
private readonly NavigationManager _navManager;
public RunModeService(ProtectedSessionStorage ProtectedSessionStore, NavigationManager NavManager)
{
// Constructor is called again if user refreshes the page.
// If the user is on a page that does not contain the startup query string
// then the query string is lost / overwritten with null.
_protectedSessionStore = ProtectedSessionStore;
_navManager = NavManager;
_navManager.TryGetQueryString("mode", out string mode);
// ProtectedSessionStorage is async only
// Can't check or set session storage
_rms.RunMode = mode;
}
Since ProtectedSessionStorage
is alive for the lifetime of the tab I thought I could check the session storage in the service constructor to handle the refresh.由于
ProtectedSessionStorage
在选项卡的生命周期内有效,我想我可以检查服务构造函数中的 session 存储来处理刷新。 Unfortunately there is no synchronous version to use in the service constructor.不幸的是,服务构造函数中没有可使用的同步版本。
2. Secondly I tried to store the query string parameters by overriding OnInitializedAsync
. 2.其次,我尝试通过覆盖
OnInitializedAsync
来存储查询字符串参数。
// App.razor
protected override async Task OnInitializedAsync()
{
_navManager.TryGetQueryString("mode", out string mode);
if ((await _protectedSessionStore.GetAsync<RunModeSettings>("RMS")).Value == null)
await _protectedSessionStore.SetAsync("RMS", new RunModeSettings() { RunMode = mode});
}
Since we can only use ProtectedSessionStorage
in asynchronous overrides it's not guaranteed that OnInitializedAsync
in App.Razor
component is completed before continuation.由于我们只能在异步覆盖中使用
ProtectedSessionStorage
,因此不能保证App.Razor
组件中的OnInitializedAsync
在继续之前完成。 This introduces a race condition between other early components like <App>
, <NavMenu>
and <MainLayout>
.这在其他早期组件(如
<App>
、 <NavMenu>
和<MainLayout>
之间引入了竞争条件。
In asp.net I could use the Session_Start
event as an entry point to store my startup query parameters for the rest of session. Is there a similar entry point in Bazor?在 asp.net 中,我可以使用
Session_Start
事件作为入口点来存储 session 的 rest 的启动查询参数。Bazor 中是否有类似的入口点?
I came up with something not so elegant but it's simple and works good.我想出了一些不太优雅但很简单而且效果很好的东西。 I register the scoped service as usual.
我像往常一样注册范围服务。
builder.Services.AddScoped<RunModeService>();
The scoped services job is to maintain startup query string parameters inside an object named RunModeSettings
.作用域服务工作是在名为
RunModeSettings
的 object 中维护启动查询字符串参数。 Upon construction of the service I use dependency injection to access the query string.在构建服务时,我使用依赖注入来访问查询字符串。 I store the settings object in the session storage incase a refresh happens on a page that does not include the startup query string parameters.
我将设置 object 存储在 session 存储中,以防在不包含启动查询字符串参数的页面上发生刷新。
To handle the race condition RunModeSettings
are accessed via GetRunModeSettingsAsync
.要处理竞争条件,可通过
RunModeSettings
访问GetRunModeSettingsAsync
。 It returns the object that the service was constructed with or pulls it from the session if ready.它返回构建服务的 object,如果准备就绪,它会从 session 中提取。
public class RunModeService
{
private RunModeSettings _rms = new RunModeSettings();
private readonly ProtectedSessionStorage _protectedSessionStore;
private readonly NavigationManager _navManager;
public RunModeService(ProtectedSessionStorage ProtectedSessionStore, NavigationManager NavManager)
{
_protectedSessionStore = ProtectedSessionStore;
_navManager = NavManager;
// Get optional parameters.
_navManager.TryGetQueryString("mode",out string mode);
_rms.RunMode = mode;
// Fire and forget.
SetRunModeAsync();
}
public async Task SetRunModeAsync()
{
if ((await _protectedSessionStore.GetAsync<RunModeSettings>("RMS")).Value == null)
await _protectedSessionStore.SetAsync("RMS", _rms);
}
public async Task<RunModeSettings> GetRunModeSettingsAsync()
{
return (await _protectedSessionStore.GetAsync<RunModeSettings>("RMS")).Value ?? _rms;
}
}
Now the lifetime of my settings within the service are not determined by the service scope. In my case I use ProtectedSessionStorage
to keep the lifetime with the tab.现在我在服务中设置的生命周期不是由服务 scope 决定的。在我的例子中,我使用
ProtectedSessionStorage
来保持选项卡的生命周期。 Finally, we can access our service as usual.最后,我们可以像往常一样访问我们的服务了。
@inject RunModeService _rms; // Page inject
[Inject] public RunModeService rms { get; set; } // Or code inject
var rms = await _rms.GetRunModeSettingsAsync();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.