递归ViewComponent导致死循环
Recursive ViewComponent causes infinite loop
我正在尝试使用 ViewComponent 制作递归类别树,但我似乎陷入了无限循环,并在一两分钟后以 HTTP 错误 502.3 - Bad Gateway 告终。
我的想法是这样的:
在主视图中,调用该组件时使用空List<ViewModelProductCategory>
作为参数,表示我想先获取根类别。
ViewComponent 在数据库中查询 ParentId == null
和 returns 的类别到 Default.cshtml
。
在 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)
),您总是会得到根类别,而不会检查任何其他内容。
我正在尝试使用 ViewComponent 制作递归类别树,但我似乎陷入了无限循环,并在一两分钟后以 HTTP 错误 502.3 - Bad Gateway 告终。
我的想法是这样的:
在主视图中,调用该组件时使用空
List<ViewModelProductCategory>
作为参数,表示我想先获取根类别。ViewComponent 在数据库中查询
ParentId == null
和 returns 的类别到Default.cshtml
。在
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)
),您总是会得到根类别,而不会检查任何其他内容。