简体   繁体   English

Blazor webassembly,在应用程序的 OnInitializedAsync 中设置服务,无法进入 Counter.razor

[英]Blazor webassembly, Setting service in App's OnInitializedAsync, can't get in Counter.razor

In blazor webassembly, I have a singleton service containing this property:在 blazor webassembly 中,我有一个包含此属性的单例服务:

public IsAuthenticatedModel Auth { get; set; } = null;

I set this property in Login page:我在登录页面中设置了这个属性:

 await genericService.SetSession<IsAuthenticatedModel>("AuthModel", ViewData.AuthModel);
 mzSingleton.Auth = ViewData.AuthModel;

First I save the data in the server session then I store it in the singleton service that I can access in the app.首先,我将数据保存在服务器会话中,然后将其存储在可以在应用程序中访问的单例服务中。

In the following code in App.razor, I check if the Singleton property is null then fill it with the data comming from server's session:在 App.razor 的以下代码中,我检查 Singleton 属性是否为空,然后用来自服务器会话的数据填充它:

protected override async Task OnInitializedAsync()
        {
            if (mzSingleton.Auth == null)
                mzSingleton.Auth = await genericService.GetSession<IsAuthenticatedModel>("AuthModel")
                    ?? new IsAuthenticatedModel();

        }

I do all of this because I want to keep service's data after refreshing the page.我这样做是因为我想在刷新页面后保留服务的数据。

Unfortunately this code does not work immediately after refresh.不幸的是,此代码在刷新后无法立即工作。 when I access the singleton service in the counter page, I have to go to another page and comeback to for it to work (Once I read, in new versions of blazor component rendering is from child to parent).当我访问计数器页面中的单例服务时,我必须转到另一个页面并返回以使其工作(一旦我阅读,在新版本的 blazor 组件中渲染是从子到父)。

Is there a workaound for this problem other than cascading parameters?除了级联参数之外,这个问题是否有解决方法? I use .Net 6.我使用.Net 6。

EDIT :编辑

in the Login page i set the service property:在登录页面中,我设置了服务属性:

await genericService.SetSession<IsAuthenticatedModel>("AuthModel", AuthModel);                
mzSingleton.Auth = AuthModel;

in the Counter.razor page:在 Counter.razor 页面中:

@if (mzSingleton.Auth != null)
{
    <h1>2 (serverside session)</h1>
    <label>Is Authenticated: </label><label>@mzSingleton.Auth.IsAuthenticated</label>
    <label>User: </label><label>@mzSingleton.Auth.User</label>
    @if (mzSingleton.Auth.Roles?.Count > 0)
    {
        foreach (string role in mzSingleton.Auth.Roles)
        {
            <label>Role: </label><label>@role</label>
        }
    }
}

As I said after refreshing counter page the mzSingleton.Auth has no value, But after doing something (when statehaschanged is fired) the page shows Auth values correctly!正如我在刷新计数器页面后所说的那样,mzSingleton.Auth 没有任何价值,但是在做某事之后(当 statehaschanged 被触发时)页面正确显示了 Auth 值!

EDIT2:编辑2:

Since I get two objects from server's session I reveresed session calls order and this time my Auth service worked and my other service NOT:由于我从服务器的会话中获得了两个对象,因此我撤销了会话调用顺序,这一次我的身份验证服务有效,而我的其他服务没有:

protected override async Task OnInitializedAsync()
{
    await base.OnInitializedAsync();
            
    mzSingleton.Auth = await genericService.GetSession<IsAuthenticatedModel>("AuthModel");

    mzSingleton.MyBooz = await genericService.GetSession<Booz>("Booz");

    StateHasChanged();    
}

So I suspected to 'async' so I replaced OnInitializedAsync to OnInitialized the synchronous version.所以我怀疑“异步”所以我将 OnInitializedAsync 替换为 OnInitialized 同步版本。 So I had to remove await and add result like this:所以我不得不删除等待并添加这样的结果:

genericService.GetSession<IsAuthenticatedModel>("AuthModel").Result; 

But I get a Blazor error that says: " Cannot wait on monitors on this runtime. ", So I forced to change the genericservice methods to synchronous versions:但是我收到一个 Blazor 错误,上面写着:“无法在此运行时等待监视器。 ”,所以我被迫将 genericservice 方法更改为同步版本:

public async Task<T> GetSession<T>(string key) where T : class, new()
to 
public T GetSession<T>(string key) where T : class, new()

But inside this method I use:但在这种方法中,我使用:

await httpClient.GetJsonAsync<SessionKeyValue>($"api/Session/GetSession/{key}");

If I remove await and Use .Result at the end I get the same error.如果我在最后删除 await 和 Use .Result我会得到同样的错误。 and if I want to use non async .GetJson() There is no such method in Blazor's HttpClient.如果我想使用非异步.GetJson()在 Blazor 的 HttpClient 中没有这样的方法。 So I locked to use Async methods.所以我锁定使用异步方法。 And if there are two Async calls in OnInitializedAsync one of them executes with delay, And is not ready after page refresh!如果 OnInitializedAsync 中有两个 Async 调用,其中一个会延迟执行,并且在页面刷新后还没有准备好!

I solved my problem with this trick: first I defined ServicesSet property in the singleton service:我用这个技巧解决了我的问题:首先我在单例服务中定义了ServicesSet属性:

public class MzSingleton
    {
        public Booz MyBooz { get; set; }

        public IsAuthenticatedModel Auth { get; set; }
        
        public Action ServicesSet { get; set; }
    }

Then in the App.razor:然后在 App.razor 中:

protected override async Task OnInitializedAsync()
        {
            await base.OnInitializedAsync();
           
            mzSingleton.Auth = await genericService.GetSession<IsAuthenticatedModel>("AuthModel");
            mzSingleton.MyBooz = await genericService.GetSession<Booz>("Booz");
            mzSingleton.ServicesSet?.Invoke();            
            
        }

And in Counter.razor:在 Counter.razor 中:

protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        mzSingleton.ServicesSet += () => StateHasChanged();
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM