简体   繁体   English

在 Blazor 视图中调用异步方法

[英]Calling async methods in Blazor view

I have a server-side blazor client and I'm trying to modify the MainLayout razor page by having a Login check.我有一个服务器端 blazor 客户端,我正在尝试通过登录检查来修改 MainLayout razor 页面。 I'm currently using Blazored for localstorage saving, and I'm currently using to see if a token is saved to see if user is logged in, however I'm not sure how I translate this in the if statement in razor page because it wants async method.我目前正在使用 Blazored 进行本地存储保存,并且我目前正在使用来查看是否保存了令牌以查看用户是否已登录,但是我不确定如何在 razor 页面的 if 语句中翻译它,因为它想要异步方法。

My login check is pretty simple as shown below.我的登录检查非常简单,如下所示。

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

In my Razor page I'm doing this statement check - which obvious doesn't work as there's no async modifier在我的 Razor 页面中,我正在执行此语句检查 - 这显然不起作用,因为没有异步修饰符

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

I've also tried doing it using the.Result property, but this results in an exception thrown: (System.AggregateException: 'Information: Executed an implicit handler method, returned result Microsoft.AspNetC)' with an inner-exception -> NullReferenceException: Object reference not set to an instance of an object.我也尝试过使用 .Result 属性,但这会导致抛出异常: (System.AggregateException: 'Information: Executed an implicit handler method, returned result Microsoft.AspNetC)' with an internal-exception -> NullReferenceException :Object 引用未设置为 object 的实例。

But from what I can see AppState is injected correctly and the local storage seems to be injected correctly in AppState.但是从我可以看到 AppState 被正确注入,并且本地存储似乎在 AppState 中被正确注入。

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

So my question is what is the correct way to approach this, is there a way to execute async methods in razor pages?所以我的问题是解决这个问题的正确方法是什么,有没有办法在 razor 页面中执行异步方法?

is there a way to execute async methods in razor pages?有没有办法在 razor 页面中执行异步方法?

No, there isn't a way to use await in a Razor component.不,没有办法在 Razor 组件中使用 await。 This is because you can't do async work as part of the rendering of the component.这是因为您不能将异步工作作为组件渲染的一部分。

Incidentally, the local storage mechanism provided by the Blazor team supports data protection, and is recommended for use by Steve Sanderson.顺便提一下,Blazor 团队提供的本地存储机制支持数据保护,推荐给 Steve Sanderson。

Note: The async Lifecycle methods of the component are where async work is done, and thus you can design your code accordingly, as for instance, calling AppState.IsLoggedIn() from OnInitializedAsync, and assigning the returned value to a local variable which can be accessed from your views.注意:组件的 async Lifecycle 方法是完成异步工作的地方,因此您可以相应地设计代码,例如,从 OnInitializedAsync 调用 AppState.IsLoggedIn(),并将返回的值分配给本地变量,该变量可以是从您的视图访问。

AsyncComponent.razor异步组件.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); });
        }
    }

Usage用法

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

Based on LazZiya example, worked for me.基于 LazZiya 示例,为我工作。 In my case an event was not async as supported by a component, but the call I had required await.在我的情况下,一个事件不是组件支持的异步,而是我需要等待的调用。 Using this example I could return data from the call based on a model.使用此示例,我可以从基于 model 的调用中返回数据。

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

I ended up with this and it worked like a charm.我最终得到了这个,它就像一个魅力。

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

Here is what I have dome to run async method in razor component partial class:这是我在 razor 组件部分 class 中运行异步方法的圆顶:

public partial class FooComponent : IComponent
{
    [Inject]
    public FooService Service { get; set; }

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

in the UI side simply call the Name param:在 UI 端只需调用Name参数:

<h3>@Name</h3>

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

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