【问题标题】:Calling async methods in Blazor view在 Blazor 视图中调用异步方法
【发布时间】:2020-02-10 00:33:18
【问题描述】:

我有一个服务器端 blazor 客户端,我正在尝试通过登录检查来修改 MainLayout razor 页面。我目前正在使用 Blazored 进行本地存储保存,并且我目前正在使用来查看是否保存了令牌以查看用户是否已登录,但是我不确定如何在 razor 页面的 if 语句中翻译它,因为它想要异步方法。

我的登录检查非常简单,如下所示。

public async Task<bool> IsLoggedIn()
{
    return await m_localStorage.ContainKeyAsync("token").ConfigureAwait(false);
}

在我的 Razor 页面中,我正在执行此语句检查 - 这显然不起作用,因为没有异步修饰符

@if (!await AppState.IsLoggedIn()) //Requires async modifier
{
    <a href="Login" target="_blank">Login</a>
}

我也尝试过使用 .Result 属性来执行此操作,但这会导致引发异常:(System.AggregateException: 'Information: Executed an implicit handler method, returned result Microsoft.AspNetC)' with an internal-exception -> NullReferenceException:对象引用未设置为对象的实例。

但据我所见,AppState 已正确注入,并且本地存储似乎已正确注入 AppState。

@if (!AppState.IsLoggedIn().Result)
{
    <a href="Login" target="_blank">Login</a>
}

所以我的问题是解决这个问题的正确方法是什么,有没有办法在剃须刀页面中执行异步方法?

【问题讨论】:

    标签: c# blazor blazor-server-side


    【解决方案1】:

    有没有办法在 razor 页面中执行异步方法?

    不,没有办法在 Razor 组件中使用 await。这是因为您不能将异步工作作为组件渲染的一部分。

    顺便提一下,Blazor 团队提供的本地存储机制支持数据保护,建议 Steve Sanderson 使用。

    注意:组件的异步生命周期方法是完成异步工作的地方,因此您可以相应地设计代码,例如,从 OnInitializedAsync 调用 AppState.IsLoggedIn(),并将返回值分配给局部变量可以从您的视图中访问。

    【讨论】:

    • 哪种本地存储机制,我只能找到支持本地存储的第三方库,即 blazored。此外,我不能从 OnINit 方法调用它作为它的服务器端 blazor,因此 js interlop 那时还没有准备好
    • 在 AfterRenderAsync 上调用似乎有效,但我必须在 StateChanged 上调用 InvokeAsync() 否则将引发异常
    • 是的,OnAfterRenderAsync 方法是合适的地方,因为在您的应用程序预渲染时不会调用此方法。并且您必须调用 StateHasChanged 方法以使用新数据重新渲染您的组件
    • 有关 Blazor 团队的本地存储机制,请参阅本文:docs.microsoft.com/en-us/aspnet/core/blazor/…
    • 其实有办法,看我的回答
    【解决方案2】:

    AsyncComponent.razor

        @typeparam TResult
        @typeparam TInput
        @if (Result != null)
        {
            @DataReadyFragment(Result)
        }
        else if (DataMissingFragment != null)
        {
            @DataMissingFragment
        }
        @code {
            [Parameter] public RenderFragment<TResult> DataReadyFragment { get; set; }
            [Parameter] public RenderFragment DataMissingFragment { get; set; }
            [Parameter] public Func<TInput, Task<TResult>> AsyncOperation { get; set; }
            [Parameter] public TInput Input { get; set; }
            TResult Result { get; set; }
    
            protected override async Task OnAfterRenderAsync(bool firstRender)
            {
                if(firstRender)
    AsyncOperation.Invoke(Input).ContinueWith(t => { Result = t.Result; InvokeAsync(StateHasChanged); });
            }
        }
    

    用法

    <AsyncComponent TResult="User" TInput="string" Input="Pa$$W0rd" AsyncOperation="@AsyncMethodName">
        <DataReadyFragment Context="result">
            @if(result.IsLoggedIn)
             {
               <h3>Logged-In , Username:@result.Name</h3>
             }
             else
             {
              <h3>Wrong Password</h3>
             }
        </DataReadyFragment>
        <DataMissingFragment>
            <h3>Please Login :)</h3>
        </DataMissingFragment>
    </AsyncComponent>
    

    【讨论】:

    • 干得好。但我不得不改变一点: if (firstRender) { await AsyncOperation.Invoke(Input).ContinueWith(t => { Result = t.Result; InvokeAsync(StateHasChanged); });否则它会无限循环......
    • @Bronzato 是的,你说得对,我忘了添加那行代码。我会更新我的答案
    【解决方案3】:

    基于 LazZiya 示例,为我工作。在我的情况下,事件不是组件支持的异步,而是我需要等待的调用。使用此示例,我可以根据模型从调用中返回数据。

    public string Name => Task.Run(() => Service.GetNameAsync()).GetAwaiter().GetResult();
    

    我最终得到了这个,它就像一个魅力。

    Task<AssessmentResponsesModel> task = Task.Run(() => _IAssessmentResponse.CreateAsync(APIPathD, argsItem, token).GetAwaiter().GetResult());
    

    【讨论】:

    • 在运行时在 WASM 中爆炸。
    • 无法评论 WASM,这适用于问题中指定的服务器端 Blazor。对于 WASM,有些事情有不同的解决方案。
    【解决方案4】:

    这是我在 razor 组件部分类中运行异步方法的圆顶:

    public partial class FooComponent : IComponent
    {
        [Inject]
        public FooService Service { get; set; }
    
        public string Name => Task.Run(() => Service.GetNameAsync()).GetAwaiter().GetResult();
    }
    

    在 UI 端只需调用 Name 参数:

    <h3>@Name</h3>
    

    【讨论】:

    • 这在 WASM 运行时会爆炸。
    猜你喜欢
    • 1970-01-01
    • 2015-12-02
    • 2021-03-24
    • 2021-02-06
    • 1970-01-01
    • 2022-10-14
    • 2015-11-09
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多