You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的设计逻辑是绑定模型的属性/字段,或支持索引器访问的表达式,它无法直接处理带参数的方法调用。这个方法需要解析出可绑定的表达式来生成对应显示模板,而你写的方法调用不符合这个要求,因此触发了异常。

可行解决方案

  1. 直接调用方法输出(最简单方案)
    既然只是要显示分类名称,不需要借助DisplayFor,直接调用方法即可:

    <td>
        @Model.GetCategoryName(item.Category_Id)
    </td>
    
  2. 提前预处理关联数据
    在后台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>
    
  3. 自定义显示模板(进阶可选)
    若坚持要用DisplayFor,可以为int?类型编写自定义显示模板,在模板内部调用模型的方法,但这个方案对于当前场景过于繁琐,不推荐。

关于RenderAction

ASP.NET MVC5的RenderAction在Razor Pages中对应的是ViewComponent或Partial视图,但你的场景只是简单显示分类名称,前面两种方案已经足够高效,无需使用组件。

内容的提问来源于stack exchange,提问作者dafie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:18:07