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

使用Tuple作为视图模型时,提交表单后控制器Action中List对象为空的问题求助

使用Tuple作为视图模型时,提交表单后控制器Action中List对象为空的问题求助

嗨,我来帮你排查这个问题!你的核心问题出在Tuple的只读特性和模型绑定的字段名不匹配这两点上,咱们一步步来解决:

为什么你的代码没拿到数据?

  1. Tuple的属性是只读的:ASP.NET Core的模型绑定需要对象有可写入的属性(带set方法),但传统Tuple的Item1、Item2都是只读的,绑定器没法把表单提交的值赋值进去。
  2. 字段名和Action参数不匹配:你手动设置了表单输入框的name为Item1[{i}].Level1,但控制器Action的参数是List<CompanyPricingLevels> levels,模型绑定会找名为levels的字段,自然匹配不上,导致levels为空。

最佳解决方案:自定义ViewModel

Tuple虽然方便,但不适合做MVC的视图模型,最好创建一个专门的视图模型类,这样既清晰又能完美支持模型绑定:

1. 创建自定义ViewModel类

public class CompanyPricingViewModel
{
    // 对应原来Tuple的Item1
    public List<CompanyPricingLevels> PricingLevels { get; set; }
    // 对应原来Tuple的Item2
    public CompanyModuleDetails ModuleDetails { get; set; }
}

2. 修改视图代码

把模型类型换成自定义的ViewModel,同时移除手动设置的@Name(让TextBoxFor自动生成正确的绑定字段名):

@model CompanyPricingViewModel

@if (Model.ModuleDetails.Module.ModuleName == "Consolidation")
{
    <div class="container">
        <h1>Company Pricing Levels</h1>
        @using (Html.BeginForm("SaveLevels", "Admin", FormMethod.Post))
        {
            <table class="table">
                <thead>
                    <tr>
                        <th>Level Type</th>
                        <th>Level 1</th>
                        <th>Level 2</th>
                        <th>Level 3</th>
                        <th>Level 4</th>
                        <th>Level 5</th>
                        <th>Level 6</th>
                    </tr>
                </thead>
                <tbody>
                    @for (int i = 0; i < Model.PricingLevels.Count; i++)
                    {
                        <tr>
                            <td>@Model.PricingLevels[i].LevelType</td>
                            <td>@Html.TextBoxFor(model => model.PricingLevels[i].Level1, new { @class = "form-control" })</td>
                            <td>@Html.TextBoxFor(model => model.PricingLevels[i].Level2, new { @class = "form-control" })</td>
                            <td>@Html.TextBoxFor(model => model.PricingLevels[i].Level3, new { @class = "form-control" })</td>
                            <td>@Html.TextBoxFor(model => model.PricingLevels[i].Level4, new { @class = "form-control" })</td>
                            <td>@Html.TextBoxFor(model => model.PricingLevels[i].Level5, new { @class = "form-control" })</td>
                            <td>@Html.TextBoxFor(model => model.PricingLevels[i].Level6, new { @class = "form-control" })</td>
                        </tr>
                    }
                </tbody>
            </table>
            <button type="submit" class="btn btn-primary">Save</button>
        }
    </div>
}

3. 修改控制器Action

现在可以直接接收自定义的ViewModel,轻松拿到提交的列表数据:

[HttpPost]
public IActionResult SaveLevels(CompanyPricingViewModel model)
{
    // 这里用model.PricingLevels就能获取到提交的所有定价级别数据了
    // 后续可以做保存逻辑
    return View();
}

备选方案(不推荐,但可以临时解决)

如果你不想创建ViewModel,也可以调整Action参数名和表单字段名匹配:

  • 把Action参数名改成Item1:public IActionResult SaveLevels(List<CompanyPricingLevels> Item1)
  • 同时移除视图里手动设置的@Name,让TextBoxFor生成Item1[{i}].LevelX的字段名,这样模型绑定就能匹配上。不过这种方式可读性差,还是推荐自定义ViewModel。

备注:内容来源于stack exchange,提问作者MarkBerry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 15:07:59