为啥“InvokeAsync”在 Blazor 组件中显示为错误?
Posted
技术标签:
【中文标题】为啥“InvokeAsync”在 Blazor 组件中显示为错误?【英文标题】:Why does 'InvokeAsync' show as an error in a Blazor component?为什么“InvokeAsync”在 Blazor 组件中显示为错误? 【发布时间】:2021-10-16 07:35:33 【问题描述】:我最近开始在我的 ASP.Net 核心 Web 应用程序中包含 Blazor 组件。我决定使用模式 [ComponentName].razor 和 [ComponentName].razor.cs 将我的组件拆分为多个文件,用于所有 C# 编码。
令人讨厌的是,我所有的状态更改通知调用都显示为错误。现在,当我构建和运行应用程序时,这些错误消失了,但它们仍然阻塞了我的错误列表窗口。如果我关闭然后打开 Visual Studio 2019,这些将消失,但它们会在几分钟后恢复。发生了什么?如何解决这些错误?
干杯!
InvokeAsync highlighted as an error
编辑:根据要求,这是一些代码。违规行位于 TransactionTableView.razor.cs 中。 'await InvokeAsync(StateHasChanged)' 显示为错误。
TransactionTableView.razor
<table class="table data-table" id="taskstable">
<thead>
<tr>
@if (ShowSelect)
<th>
<input type="checkbox" @bind="SelectAllTransactions" @bind:event="oninput" @onclick="() => CheckAllTransactions(!SelectAllTransactions)"/>
Select all
</th>
@if (ShowParent)
<th>
Parent
</th>
<th>
Task
</th>
<th>
Status
</th>
<th>
Due Date
</th>
<th>
Completion Date
</th>
<th>
Amount Due
</th>
<th>
Amount Paid
</th>
<th>
Comments
</th>
</tr>
</thead>
<tbody class="tasks-body">
@if (Transactions != null)
@foreach (var transaction in DisplayTransactions)
<tr class="@transaction.AlertClassDisplay()">
@if (ShowSelect)
<td>
<input @bind="transaction.Select" type="checkbox" @oninput="() => SelectSingleTask(transaction.TransactionId)"/>
</td>
@if (ShowParent)
<td>
@transaction.TenementKey
</td>
<td>
@transaction.Description
</td>
<td class="task-status">
<a asp-action="Details" asp-controller="Alerts" method="get" asp-route-transactionId="@transaction.TransactionId">
@transaction.TransactionStatus
</a>
</td>
<td>
@transaction.DueDateDisplay()
</td>
<td>
@($"transaction.CompletionDate:dd MMM yyyy")
</td>
<td>
@transaction.AmountDue
</td>
<td>
@transaction.AmountPaid
</td>
<td>
@transaction.Comments
</td>
</tr>
</tbody>
</table>
TransactionTableView.razor.cs
partial class TransactionTableView
// Injected services
[Inject]
private ApplicationDbContext _context get; set;
// Data
public List<int> TenementIds get; set;
public List<TransactionViewModel> Transactions get; set;
public List<TransactionViewModel> DisplayTransactions get; set;
public List<Filter> Filters get; set; = new List<Filter>();
private bool ShowParent get; set; = true;
private bool ShowSelect get; set; = true;
private bool SelectAllTransactions get; set; = false;
public async Task Refresh()
var transactions = new List<Transaction>(_context.Transactions.Where(x => x.TenementId != null && TenementIds.Contains((int)x.TenementId)));
transactions = transactions.OrderBy(x => x.DueDate).ToList();
var models = new List<TransactionViewModel>();
transactions.ForEach(x =>
models.Add(x.GetViewModel(_context));
);
Transactions = models;
await RefreshFilters();
public async Task RefreshFilters()
var holder = Transactions;
if (Filters != null)
foreach (var filter in Filters)
if(filter.FilteringProperty.PropertyType == typeof(string))
holder = holder.Where(x => ((string)filter.FilteringProperty.GetValue(x)).ToLower().Contains(filter.Values.First().ToString().ToLower())).ToList();
if(filter.FilteringProperty.PropertyType == typeof(DateTime) || filter.FilteringProperty.PropertyType == (typeof(DateTime?)))
var dFilter = (DateFilter)filter;
if (dFilter.SelectedAfterDate)
holder = holder.Where(x => (DateTime)dFilter.FilteringProperty.GetValue(x) > dFilter.TargetDate).ToList();
else if (dFilter.SelectBeforeDate)
holder = holder.Where(x => (DateTime)dFilter.FilteringProperty.GetValue(x) < dFilter.TargetDate).ToList();
else if (dFilter.SelectBetweenDates)
holder = holder.Where(x =>
var targetDate = (DateTime)dFilter.FilteringProperty.GetValue(x);
return targetDate < dFilter.TargetDate && targetDate > (DateTime)dFilter.FirstTargetDate;
).ToList();
if(filter.FilteringProperty.PropertyType == typeof(TransactionStatus))
var targetStatuses = filter.Values.Select(x => (TransactionStatus)x);
holder = holder.Where(x => targetStatuses.Contains(x.TransactionStatus)).ToList();
DisplayTransactions = holder;
await RefreshAllTaskSelector();
await InvokeAsync(StateHasChanged);
private async Task CheckAllTransactions(bool checkAll)
foreach(var displayTask in DisplayTransactions)
displayTask.Select = checkAll;
await InvokeAsync(StateHasChanged);
private async Task SelectSingleTask(int transactionId)
var task = DisplayTransactions.SingleOrDefault(x => x.TransactionId == transactionId);
task.Select = !task.Select;
if (DisplayTransactions.Any() && DisplayTransactions.Where(x => !x.Select).Count() == 0)
SelectAllTransactions = true;
else
SelectAllTransactions = false;
await InvokeAsync(StateHasChanged);
private async Task RefreshAllTaskSelector()
if (DisplayTransactions.Any() && DisplayTransactions.Where(x => !x.Select).Count() == 0)
SelectAllTransactions = true;
else
SelectAllTransactions = false;
private async Task DeleteSelected()
if (_context.ChangeTracker.HasChanges())
throw new ApplicationException("DB already has changes");
var targets = new List<TransactionViewModel>(DisplayTransactions.Where(x => x.Select));
foreach(var target in targets)
Transactions.Remove(target);
DisplayTransactions.Remove(target);
var transaction = _context.Transactions.SingleOrDefault(x => x.TransactionId == target.TransactionId);
_context.Transactions.Remove(transaction);
await _context.SaveChangesAsync();
await InvokeAsync(StateHasChanged);
private async Task CompleteSelected()
if (_context.ChangeTracker.HasChanges())
throw new ApplicationException("DB already has changes");
var targets = new List<TransactionViewModel>(DisplayTransactions.Where(x => x.Select));
foreach (var target in targets)
var dbTask = _context.Transactions.SingleOrDefault(x => x.TransactionId == target.TransactionId);
dbTask.CompletionDate = DateTime.Now;
dbTask.TransactionStatus = TransactionStatus.Completed;
target.CompletionDate = dbTask.CompletionDate;
target.TransactionStatus = dbTask.TransactionStatus;
var orig = Transactions.SingleOrDefault(x => x.TransactionId == target.TransactionId);
orig.CompletionDate = dbTask.CompletionDate;
orig.TransactionStatus = dbTask.TransactionStatus;
await _context.SaveChangesAsync();
await RefreshFilters();
await InvokeAsync(StateHasChanged);
private async Task ArchiveSelected()
if (_context.ChangeTracker.HasChanges())
throw new ApplicationException("DB already has changes");
var targets = new List<TransactionViewModel>(DisplayTransactions.Where(x => x.Select));
foreach (var target in targets)
var dbTask = _context.Transactions.SingleOrDefault(x => x.TransactionId == target.TransactionId);
dbTask.CompletionDate = DateTime.Now;
dbTask.TransactionStatus = TransactionStatus.Archived;
target.CompletionDate = dbTask.CompletionDate;
target.TransactionStatus = dbTask.TransactionStatus;
var orig = Transactions.SingleOrDefault(x => x.TransactionId == target.TransactionId);
orig.CompletionDate = dbTask.CompletionDate;
orig.TransactionStatus = dbTask.TransactionStatus;
await _context.SaveChangesAsync();
await RefreshFilters();
await InvokeAsync(StateHasChanged);
【问题讨论】:
能否分享您的代码? 你的应用是客户端(WASM)还是服务器端? 编译器好像找不到InvokeAsync
方法,但是这个方法在ComponentBase类里面。您是否尝试将 : ComponentBase
添加到类定义中?像这样:public partial class TransactionTableView : ComponentBase
现在检查调试器在哪里找到 'InvokeAsync` 方法
嗨,克里斯,如果我的回复或 Henk 的回复满足您的需求,请在此处标记答案:***.com/help/someone-answers。
【参考方案1】:
我已经尝试了一个小测试项目,我可以确认您可能有 2 个问题:
您已在 TransactionTableView.razor(如 Henk 所说)之外的另一个文件夹中创建/移动文件 TransactionTableView.razor.cs 后面的代码,但未指定 @987654321 @路径 你还没有从ComponentBase
派生你的类
如果您想分隔两个不同文件夹中的两个文件,您需要添加inherits
,如下所示:
EmployeeData.razor 在 Pages 文件夹中
@page "/employee/Id"
@using TestMenu.Shared
@using TestMenu.Client.Services
@inherits TestMenu.Client.Pages.test.EmployeeData
<h3>Employee</h3>
Result data: <b>@employeeData</b>
EmployeeData.razor.cs 在 Pages/test 文件夹中
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using TestMenu.Client.Services;
using TestMenu.Shared;
namespace TestMenu.Client.Pages.test
public partial class EmployeeData: ComponentBase
[Inject] IEmployeeService EmployeeService get; set;
[Parameter]
public string Id get; set;
protected Employee Employee = new();
protected string employeeData;
protected override async Task OnInitializedAsync()
Employee = (await EmployeeService.GetEmployeeById(int.Parse(Id)));
employeeData = Employee.Name;
await InvokeAsync(StateHasChanged);
如果您从 EmployeeData.razor.cs 后面的代码中删除 : ComponentBase
,您会收到与屏幕截图中类似的错误。
【讨论】:
就是这样!将 :ComponentBase 添加到我的 .razor.cs 类就可以了。谢谢! 现在使用继承与 2 个不同的类,而不是一个部分类。增加一点开销。以上是关于为啥“InvokeAsync”在 Blazor 组件中显示为错误?的主要内容,如果未能解决你的问题,请参考以下文章
IJSRuntime 忽略服务器端 Blazor 项目中的自定义 json 序列化程序
为啥 Blazor 使用 post 而不是 WebSockets?