在局部视图中调用 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>
不知道为什么,但我不得不在等待之前使用 @
。
我有一个局部视图 (_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>
不知道为什么,但我不得不在等待之前使用 @
。