为什么 'InvokeAsync' 在 Blazor 组件中显示为错误?

Why does 'InvokeAsync' show as an error in a Blazor component?

我最近开始在我的 ASP.Net 核心网络应用程序中包含 Blazor 组件。我决定使用模式 [ComponentName].razor 和 [ComponentName].razor.cs 将我的组件拆分为多个文件,用于所有 C# 编码。

令人讨厌的是,我所有的状态更改通知调用都显示为错误。现在,当我构建和 运行 应用程序时,这些错误消失了,但它们仍然占据了我的错误列表 window。如果我关闭然后打开 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);
        }
    }

我尝试了一个小测试项目,我可以确认您可能有 2 个问题:

  • 你有 created/moved 代码隐藏文件 TransactionTableView.razor.cs 在另一个文件夹而不是 TransactionTableView.razor(正如 Henk 所说)没有指定 @inherits 路径
  • 您还没有从 ComponentBase
  • 中得出您的 class

如果你想分开两个不同文件夹中的两个文件你需要添加inherits,就像这里:

EmployeeData.razorPages 文件夹中

@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.csPages/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,您会收到类似于屏幕截图中的错误。