递归ViewComponent导致死循环

Recursive ViewComponent causes infinite loop

我正在尝试使用 ViewComponent 制作递归类别树,但我似乎陷入了无限循环,并在一两分钟后以 HTTP 错误 502.3 - Bad Gateway 告终。

我的想法是这样的:

  1. 在主视图中,调用该组件时使用空List<ViewModelProductCategory>作为参数,表示我想先获取根类别。

  2. ViewComponent 在数据库中查询 ParentId == null 和 returns 的类别到 Default.cshtml

  3. Default.cshtml 中再次调用该组件,但这次使用子类别列表作为参数。

我正在这样调用 ViewComponent:

@await Component.InvokeAsync("SelectCategories", 
        new List<MyStore.Models.ViewModels.ViewModelProductCategory> { })

ViewComponent class 看起来像这样:

using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MyStore.Models;
using MyStore.Models.ViewModels;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace MyStore.Areas.Admin.ViewComponents
{
    public class SelectCategoriesViewComponent : ViewComponent
    {
        private readonly MyStoreContext _context;
        private readonly IMapper _mapper;

        public SelectCategoriesViewComponent(MyStoreContext context, IMapper mapper)
        {
            _context = context;
            _mapper = mapper;
        }

        public async Task<IViewComponentResult> InvokeAsync(List<ViewModelProductCategory> catList)
        {
            List<ViewModelProductCategory> VM = await GetCategoriesAsync(catList);
            return View(VM);
        }

        private async Task<List<ViewModelProductCategory>> GetCategoriesAsync(List<ViewModelProductCategory> catList)
        {
            List<ViewModelProductCategory> VM = new List<ViewModelProductCategory>();
            if (catList.Count() == 0)
            {
                VM = _mapper.Map<List<ViewModelProductCategory>>
                    (await _context.ProductCategories
                    .Where(x => x.ParentId == null)
                    .ToListAsync());
            }
            else
            {
                VM = catList;
            }
            return VM;
        }
    }
}

ViewComponent 的 Default.cshtml 看起来像这样:

@model IEnumerable<MyStore.Models.ViewModels.ViewModelProductCategory>
<ul style="list-style:none;padding-left:0px;">
    @if (Model != null)
    {
        foreach (var item in Model)
        {
            <li style="margin-top:4px;padding:0px;">
                @Html.HiddenFor(m => item.Id)
                @Html.CheckBoxFor(m => item.Checked)
                @Html.LabelFor(m => item.Id, item.Title)
                <ul>
                    @await Component.InvokeAsync("SelectCategories", item.Children)
                </ul>
            </li>
        }
    }
</ul>

哪里is/are error/s?

编辑

Tarek.Eladly 的评论让我意识到我在 GetCategoriesAsync 方法中存在严重的逻辑缺陷。我对我的代码进行了这些更改,现在它可以工作了:

第一次调用ViewComponent:

@await Component.InvokeAsync("SelectCategories",
new
{
    root = true,
    catList = new List<MyStore.Models.ViewModels.ViewModelProductCategory>()
})

ViewComponent 方法:

public async Task<IViewComponentResult> InvokeAsync(bool root, List<ViewModelProductCategory> catList)
{
    List<ViewModelProductCategory> VM = await GetCategoriesAsync(root, catList);
    return View(VM);
}

private async Task<List<ViewModelProductCategory>> GetCategoriesAsync(bool root, List<ViewModelProductCategory> catList)
{
    List<ViewModelProductCategory> VM = new List<ViewModelProductCategory>();
    if (root)
    {
        VM = _mapper.Map<List<ViewModelProductCategory>>
            (await _context.ProductCategories
            .Where(x => x.ParentId == null)
            .ToListAsync());
    }
    else
    {
        VM = catList;
    }
    return VM;
}

调用 Default.cshtml 中的 ViewComponent:

@await Component.InvokeAsync("SelectCategories",
new
{
    root = false,
    catList = item.Children
})

:)

如果我是对的,请看一下 GetCategoriesAsync 中的 (.Where(x => x.ParentId == null)),您总是会得到根类别,而不会检查任何其他内容。