Razor Pages调用PageModel方法触发InvalidOperationException异常求助
问题描述
这是我的razor pages模型类:
public class IndexModel : PageModel { private readonly IPaymentService _paymentService; private readonly ICategoryService _categoryService; public IEnumerable<PaymentEntity> Entities { get; set; } = default!; public IEnumerable<CategoryEntity> Categories { get; set; } = default!; public string GetCategoryName(int? id) => (id == null) ? "" : Categories.Single(x => x.Id == id).Name; public IndexModel(IPaymentService paymentService, ICategoryService categoryService) { _paymentService = paymentService; _categoryService = categoryService; } public async Task OnGetAsync() { Entities = await _paymentService.GetAll(); Cities = new SelectList(await _categoryService.GetAll(), "Id", "Title"); } }
以下是我在视图页面中使用该类的方式:
@page @model IndexModel <table class="table"> <tr> <th>Name</th> <th>Category name</th> </tr> @foreach (var item in Model.Entities) { <tr> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(x => Model.GetCategoryName((item.Category_Id))) </td> </tr> } </table>
但我遇到了异常:
InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.
异常出现在这一行:@Html.DisplayFor(x => Model.GetCategoryName((item.Category_Id)))。请问问题出在哪里?我记得ASP.NET MVC5中有RenderAction方法可以实现类似功能。
问题原因与解决办法
报错根源
Html.DisplayFor的设计逻辑是绑定模型的属性/字段,或支持索引器访问的表达式,它无法直接处理带参数的方法调用。这个方法需要解析出可绑定的表达式来生成对应显示模板,而你写的方法调用不符合这个要求,因此触发了异常。
可行解决方案
直接调用方法输出(最简单方案)
既然只是要显示分类名称,不需要借助DisplayFor,直接调用方法即可:<td> @Model.GetCategoryName(item.Category_Id) </td>提前预处理关联数据
在后台OnGetAsync中把支付数据和分类名称预先关联好,用DTO或匿名类型包装后传递给视图,这样就能在视图里用DisplayFor绑定属性:public async Task OnGetAsync() { var allPayments = await _paymentService.GetAll(); var allCategories = await _categoryService.GetAll(); // 用匿名类型包装关联后的数据 Entities = allPayments.Select(p => new { p.Id, p.Name, p.Category_Id, CategoryName = allCategories.FirstOrDefault(c => c.Id == p.Category_Id)?.Name ?? "" }); // 修复原代码里的笔误:Cities应该是Categories Categories = new SelectList(allCategories, "Id", "Title"); }视图中直接绑定属性:
<td> @Html.DisplayFor(modelItem => item.CategoryName) </td>自定义显示模板(进阶可选)
若坚持要用DisplayFor,可以为int?类型编写自定义显示模板,在模板内部调用模型的方法,但这个方案对于当前场景过于繁琐,不推荐。
关于RenderAction
ASP.NET MVC5的RenderAction在Razor Pages中对应的是ViewComponent或Partial视图,但你的场景只是简单显示分类名称,前面两种方案已经足够高效,无需使用组件。
内容的提问来源于stack exchange,提问作者dafie
相关产品推荐
相关产品推荐

