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

如何在无JavaScript的ASP.NET表单中创建含Fruit列表的Basket对象

无JavaScript实现同表单提交Basket与动态数量Fruit的方案

完全不需要前端脚本,靠ASP.NET Core原生模型绑定规则+原生表单提交能力就能实现,核心是通过服务端往返处理新增行的逻辑,所有已填内容不会丢失。


1. 先定义表单专用的视图模型

不要直接用数据库实体类接收表单值,单独建接收提交的模型,增加动作标识字段区分用户是点了「新增水果行」还是「最终提交」:

public class CreateBasketVm
{
    public string Sharp { get; set; }
    public string Material { get; set; }
    public List<FruitItem> Fruits { get; set; } = new();
    // 标识当前提交的动作类型
    public string SubmitAction { get; set; }
}

public class FruitItem
{
    public string Color { get; set; }
    public string Taste { get; set; }
}

2. 编写后端Action逻辑

两个接口,一个负责初始化表单页,一个负责处理所有表单提交(新增行、最终保存都走这一个Post接口):

// 初始化创建页
[HttpGet]
public IActionResult Create()
{
    var vm = new CreateBasketVm
    {
        // 默认给1行水果输入位
        Fruits = new List<FruitItem> { new() }
    };
    return View(vm);
}

[HttpPost]
public IActionResult Create(CreateBasketVm vm)
{
    // 判断提交动作:如果是点了新增水果
    if (vm.SubmitAction == "AddFruit")
    {
        // 给水果集合加一个空的新项,返回视图时会自动渲染新的输入行
        vm.Fruits.Add(new FruitItem());
        // 不要清空ModelState,否则之前用户填的内容会丢失
        return View(vm);
    }

    // 走到这就是最终提交保存,走正常校验+入库逻辑
    if (ModelState.IsValid)
    {
        var entity = new Basket
        {
            Sharp = vm.Sharp,
            Material = vm.Material,
            Fruits = vm.Fruits.Select(f => new Fruit
            {
                Color = f.Color,
                Taste = f.Taste
            }).ToList()
        };
        // 这里替换成你自己的数据库保存逻辑即可
        // _context.Baskets.Add(entity);
        // await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }
    // 校验不通过直接返回视图显示错误
    return View(vm);
}

3. 修改Razor表单代码

核心要遵守ASP.NET Core集合绑定的命名规则:集合输入框的name必须是集合名[索引].属性名的格式,用for循环遍历渲染就能自动生成符合规则的name值,不需要手动写。

<form method="post">
    <div style="margin: 8px 0;">
        <label>篮子材质:</label>
        <input asp-for="Material" />
        <span asp-validation-for="Material" class="text-danger"></span>
    </div>
    <div style="margin: 8px 0;">
        <label>篮子形状:</label>
        <input asp-for="Sharp" />
        <span asp-validation-for="Sharp" class="text-danger"></span>
    </div>

    <h4>录入水果信息</h4>
    @for (int i = 0; i < Model.Fruits.Count; i++)
    {
        <div style="margin: 10px 0; padding: 10px; border: 1px solid #eee;">
            <p>第@(i+1)个水果</p>
            <div style="margin: 5px 0;">
                <label>颜色:</label>
                <input asp-for="Fruits[i].Color" />
            </div>
            <div style="margin: 5px 0;">
                <label>口味:</label>
                <input asp-for="Fruits[i].Taste" />
            </div>
        </div>
    }

    <!-- 新增行按钮:点击后直接提交表单,后端识别动作后加新行返回 -->
    <button type="submit" name="SubmitAction" value="AddFruit">新增水果行</button>
    <!-- 最终保存按钮 -->
    <button type="submit" name="SubmitAction" value="Save" style="margin-left: 20px;">提交保存</button>
</form>

实现说明

  • 全程没有任何JavaScript代码,所有交互靠原生HTML表单提交能力实现,兼容所有浏览器
  • 点击「新增水果行」时,用户之前填的所有篮子信息、已录入的水果信息都会随表单一起提交到后端,后端新增空项后返回视图时,tag helper会自动把之前提交的值回填到输入框,不会出现内容丢失的问题
  • 如果需要支持删除行,逻辑完全一致:给每一行加个删除按钮,点击时提交要删除的行索引,后端从Fruits集合里移除对应项再返回视图即可,同样不需要脚本
  • 只要严格按照索引格式渲染输入框,ASP.NET Core会自动把提交的多个Fruit值绑定到List集合属性上,不需要额外做参数解析

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 02:42:18