在 Blazor 视图中调用异步方法
Calling async methods in Blazor view
我有一个服务器端 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 inner-exception -> NullReferenceException : 对象引用未设置为对象的实例。
但据我所知,AppState 已正确注入,本地存储似乎已正确注入 AppState。
@if (!AppState.IsLoggedIn().Result)
{
<a href="Login" target="_blank">Login</a>
}
所以我的问题是解决这个问题的正确方法是什么,有没有办法在剃刀页面中执行异步方法?
is there a way to execute async methods in razor pages?
不,无法在 Razor 组件中使用 await。这是因为您不能将异步工作作为组件呈现的一部分。
顺带一提,Blazor团队提供的本地存储机制支持数据保护,推荐Steve Sanderson使用
注意:组件的异步生命周期方法是完成异步工作的地方,因此您可以相应地设计代码,例如,从 OnInitializedAsync 调用 AppState.IsLoggedIn(),并分配返回值到可以从您的视图访问的局部变量。
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>
这是我在 razor 组件部分 class 中对 运行 异步方法的圆顶
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>
基于 LazZiya 示例,对我有用。在我的例子中,事件不是组件支持的异步事件,而是我需要等待的调用。使用此示例,我可以 return 来自基于模型的调用的数据。
public string Name => Task.Run(() => Service.GetNameAsync()).GetAwaiter().GetResult();
我最终得到了这个,它非常有效。
Task<AssessmentResponsesModel> task = Task.Run(() => _IAssessmentResponse.CreateAsync(APIPathD, argsItem, token).GetAwaiter().GetResult());
我有一个服务器端 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 inner-exception -> NullReferenceException : 对象引用未设置为对象的实例。
但据我所知,AppState 已正确注入,本地存储似乎已正确注入 AppState。
@if (!AppState.IsLoggedIn().Result)
{
<a href="Login" target="_blank">Login</a>
}
所以我的问题是解决这个问题的正确方法是什么,有没有办法在剃刀页面中执行异步方法?
is there a way to execute async methods in razor pages?
不,无法在 Razor 组件中使用 await。这是因为您不能将异步工作作为组件呈现的一部分。
顺带一提,Blazor团队提供的本地存储机制支持数据保护,推荐Steve Sanderson使用
注意:组件的异步生命周期方法是完成异步工作的地方,因此您可以相应地设计代码,例如,从 OnInitializedAsync 调用 AppState.IsLoggedIn(),并分配返回值到可以从您的视图访问的局部变量。
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>
这是我在 razor 组件部分 class 中对 运行 异步方法的圆顶
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>
基于 LazZiya 示例,对我有用。在我的例子中,事件不是组件支持的异步事件,而是我需要等待的调用。使用此示例,我可以 return 来自基于模型的调用的数据。
public string Name => Task.Run(() => Service.GetNameAsync()).GetAwaiter().GetResult();
我最终得到了这个,它非常有效。
Task<AssessmentResponsesModel> task = Task.Run(() => _IAssessmentResponse.CreateAsync(APIPathD, argsItem, token).GetAwaiter().GetResult());