Blazor 服务器存储初始查询参数

发布于 2025-01-20 04:54:33 字数 1884 浏览 1 评论 0原文

问题:在会话生命周期中存储启动查询字符串。这些启动查询字符串是可选参数("?mode=run"),并且不会在页面之间保留。我很难找到一个入口点来设置 ProtectedSessionStorage

1. 首先,我尝试了具有依赖注入的作用域服务。在用户刷新页面之前,这种方法效果很好。

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;
         
}

由于 ProtectedSessionStorage 在选项卡的生命周期内一直处于活动状态,我想我可以检查服务构造函数中的会话存储来处理刷新。不幸的是,服务构造函数中没有可使用的同步版本。

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});

}

由于我们只能在异步重写中使用 ProtectedSessionStorage,因此不能保证 App.Razor 组件中的 OnInitializedAsync 在继续之前完成。这引入了其他早期组件(例如 之间的竞争条件)。

在 asp.net 中,我可以使用 Session_Start 事件作为入口点来存储会话其余部分的启动查询参数。 Bazor 中有类似的入口点吗?

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. I'm having a hard time finding a single entry point to set the ProtectedSessionStorage.

1. First I tried a scoped service with dependency injection. 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. 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.

// 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. This introduces a race condition between other early components like <App>, <NavMenu> and <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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心病无药医 2025-01-27 04:54:33

我想出了一些不那么优雅的东西,但它很简单并且效果很好。我像往常一样注册范围的服务。

builder.Services.AddScoped<RunModeService>();

范围的服务作业是在一个名为runmodesettings的对象中维护启动查询字符串参数。服务施工后,我使用依赖注入来访问查询字符串。我将设置对象存储在会话存储中,而不是在不包括启动查询字符串参数的页面上进行刷新。

要处理竞赛条件runmodesettings通过getRunmodesettingsasync访问。它返回了服务是由服务构建或从会话中拉出的对象。

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;
    }

}

现在,我在服务中的设置的寿命不是由服务范围确定的。在我的情况下,我使用protectedSessionStorage将使用选项卡保持寿命。最后,我们可以照常访问我们的服务。

@inject RunModeService _rms; // Page inject
[Inject] public RunModeService rms { get; set; } // Or code inject

var rms = await _rms.GetRunModeSettingsAsync();

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. 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.

To handle the race condition RunModeSettings are accessed via GetRunModeSettingsAsync. It returns the object that the service was constructed with or pulls it from the session if ready.

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. 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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文