在局部视图中调用 ASP.NET 核心视图组件

Invoke an ASP.NET Core View Component inside a Partial View

我有一个局部视图 (_FormCustomer),它显示了一个用于创建客户的表单。我还有一个生成国家选项列表的视图组件 (Countrylist)。现在我想在我的表单中显示国家列表。这就是我所做的:

Index.cshtml

<partial name="_FormCustomer" for="@Model._Customer" />

_FormCustomer.cshtml

<select asp-for="@Model.Land" class="form-control">
    @await Component.InvokeAsync("Countrylist");
</select>

CountrylistViewComponent.cs

public async Task<IViewComponentResult> InvokeAsync()
{
    return View(await _countryRepository.GetCountriesAsync());
}

(函数 GetCountriesAsync() returns 国家列表;这很好用。)

Pages/Componenst/Countrylist/default.cshtml

@model List<Country>
@foreach (Country country in Model)
{
    <option value="@country.code">@country.name</option>
}

不幸的是,当我调用部分时,select-box 保持为空。但是,当我直接从 Index.cshtml 调用 @await Component.InvokeAsync("Countrylist"); 时,它工作正常。

所以看起来您不能在分部视图中使用视图组件。这个结论对吗?还是我做错了什么?

我现在已经测试了这种情况并且可以确认数据加载正常 - 无论是当视图组件直接包含在页面上还是包含在部分视图中时。 (我已经在 Razor 页面上对此进行了测试 - 但在使用 MVC 时它可能会以同样的方式工作。如果您使用的是 MVC 或 Razor 页面,您没有提到。)

您可以尝试一些方法来查看加载是否正常:

1) 从所有 "Select" 和 "Partials" 中删除 "for*" 属性。这样您就可以首先检查数据是否加载,然后您就可以担心绑定到 selected 项目。 (此外,在您提供的代码中,您省略了模型变量 - 因此无法对它们发表评论。)

2) 去掉最后一个“;”在你的 _FormCustomer.cshtml

<select asp-for="@Model.Land" class="form-control">
    @await Component.InvokeAsync("Countrylist")
</select>

请注意,我已经删除了尾随的“;”在等待声明中。我注意到“;”已作为另一个 "option" 添加到 select !

3) 我还注意到,即使是很小的语法错误(Intellisense 未发现)也会导致 select 无法加载。调试以查看您的 InvokeAsync 是否实际被调用 - 在存在轻微语法错误的情况下,InvokeAsync 甚至没有被调用。

另外请记住:

"When a partial view is instantiated, it receives a copy of the parent's ViewData dictionary. Updates made to the data within the partial view aren't persisted to the parent view. ViewData changes in a partial view are lost when the partial view returns."

感谢Phantom2018,在你post.

之后发现了问题

@0:我正在使用 Razor 页面

@1:这没有效果

@2:这是我问题中的错字,而不是我的代码中的错字

@3: 调试器告诉我 vie 组件被调用了,所以

我的实际代码有点不同,我想预先select一个国家,如果它可用的话:

<select asp-for="@Model.Country" class="form-control">
    @if (Model == null)
    {
        await Component.InvokeAsync("Countrylist");
    }
    else
    {
        await Component.InvokeAsync("Countrylist", Model.Country);
    }  
</select>

经过一些测试,我找到了解决方案:

<select asp-for="@Model.Country" class="form-control">
    @if (Model == null)
    {
        @await Component.InvokeAsync("Countrylist");
    }
    else
    {
        @await Component.InvokeAsync("Countrylist", Model.Country);
    }  
</select>

不知道为什么,但我不得不在等待之前使用 @