使用C# Razor Pages返回PartialView时出现多构造函数错误
错误信息
InvalidOperationException: Multiple constructors accepting all given argument types have been found in type 'System.Collections.Generic.List`1[DantronikOrganizer.Data.Models.UserVacationEntity]'. There should only be one applicable constructor.
问题根源
错误出在Partial视图的配置上:你的_TableView.cshtml开头添加了@page指令,这会让该视图被识别为独立的Razor Page,而非用于嵌入的Partial View。当你从PageModel返回Partial("_TableView", UserVacationList)时,Razor试图初始化该视图的模型(List<UserVacationEntity>),但List<T>包含多个可匹配的构造函数(无参构造、接收IEnumerable<T>的构造等),Razor无法自动选择,因此抛出上述错误。
此外,原代码中年份过滤的逻辑存在bug:!string.IsNullOrEmpty(year.ToString())永远为true(int类型默认值为0,转字符串是"0"而非空),导致过滤逻辑失效。
解决方案
1. 移除Partial视图的@page指令
打开_TableView.cshtml,删除开头的@page,因为Partial View不需要这个指令(它仅用于独立Razor Page)。
修改后的Partial视图:
@model List<DantronikOrganizer.Data.Models.UserVacationEntity> <table class="table table-hover"> <thead><tr> <th>@Html.DisplayNameFor(m=>m[0].DtFrom)</th> <th>@Html.DisplayNameFor(m=>m[0].DtUntil)</th> <th>@Html.DisplayNameFor(m=>m[0].DaysRequested)</th> <th>@Html.DisplayNameFor(m=>m[0].IsApproved)</th> <th></th> </tr></thead> <tbody> @if(Model!=null&&Model.Any()){ @foreach(var item in Model){ <tr> <td>@Html.DisplayFor(modelItem=>item.DtFrom)</td> <td>@Html.DisplayFor(modelItem=>item.DtUntil)</td> <td>@Html.DisplayFor(modelItem=>item.DaysRequested)</td> <td>@Html.DisplayFor(modelItem=>item.IsApproved)</td> <td> <a class="btn btn-primary" asp-page="./Edit" asp-route-id="@item.Id">Bearbeiten</a> | <a class="btn btn-primary" asp-page="./Details" asp-route-id="@item.Id">Details</a> | <button class="btn btn-danger" onclick="deleteVacation(@item.Id)">Löschen</button> </td> </tr> } }else{ <tr><td colspan="5">No vacation entries found.</td></tr> } </tbody> </table>
2. 修复年份过滤逻辑
打开_TableView.cshtml.cs,将年份过滤的判断条件从!string.IsNullOrEmpty(year.ToString())改为year != 0,因为用户输入的有效年份不会是0:
修改后的PageModel方法:
public async Task<IActionResult> OnGetTableView(int year, bool isApproved) { var user = await _userManager.GetUserAsync(User); UserVacationList = await _service.GetUserVacationByUser(user.Id); // 修复年份过滤逻辑 if(year != 0){ UserVacationList = UserVacationList.Where(u=>u.DtFrom.Year==year).ToList(); } if(isApproved){ UserVacationList = UserVacationList.Where(x=>x.IsApproved).ToList(); } return Partial("_TableView", UserVacationList); }
可选优化:使用PageModel作为Partial视图模型(更符合Razor Pages规范)
如果你想更贴合Razor Pages的设计模式,可以将Partial视图的模型改为对应的PageModel,而非直接传递List:
修改Partial视图模型
@model DantronikOrganizer.Pages.Vacation._TableView <table class="table table-hover"> <thead><tr> <th>@Html.DisplayNameFor(m=>m.UserVacationList[0].DtFrom)</th> <th>@Html.DisplayNameFor(m=>m.UserVacationList[0].DtUntil)</th> <th>@Html.DisplayNameFor(m=>m.UserVacationList[0].DaysRequested)</th> <th>@Html.DisplayNameFor(m=>m.UserVacationList[0].IsApproved)</th> <th></th> </tr></thead> <tbody> @if(Model.UserVacationList!=null&&Model.UserVacationList.Any()){ @foreach(var item in Model.UserVacationList){ <tr> <td>@Html.DisplayFor(modelItem=>item.DtFrom)</td> <td>@Html.DisplayFor(modelItem=>item.DtUntil)</td> <td>@Html.DisplayFor(modelItem=>item.DaysRequested)</td> <td>@Html.DisplayFor(modelItem=>item.IsApproved)</td> <td> <a class="btn btn-primary" asp-page="./Edit" asp-route-id="@item.Id">Bearbeiten</a> | <a class="btn btn-primary" asp-page="./Details" asp-route-id="@item.Id">Details</a> | <button class="btn btn-danger" onclick="deleteVacation(@item.Id)">Löschen</button> </td> </tr> } }else{ <tr><td colspan="5">No vacation entries found.</td></tr> } </tbody> </table>
修改PageModel返回逻辑
public async Task<IActionResult> OnGetTableView(int year, bool isApproved) { var user = await _userManager.GetUserAsync(User); UserVacationList = await _service.GetUserVacationByUser(user.Id); if(year != 0){ UserVacationList = UserVacationList.Where(u=>u.DtFrom.Year==year).ToList(); } if(isApproved){ UserVacationList = UserVacationList.Where(x=>x.IsApproved).ToList(); } // 返回PageModel本身,视图将使用Model.UserVacationList return Partial("_TableView", this); }
验证
完成修改后,重新运行项目,Ajax加载PartialView时将不再触发构造函数匹配错误,年份过滤功能也能正常工作,删除操作后表格会局部刷新。
内容的提问来源于stack exchange,提问作者user9152628

