ASP.NET Core:如何动态添加输入控件并传递数据至控制器
ASP.NET Core 实现动态添加字段并提交嵌套模型数据
1. 控制器实现
创建ServicesController,负责渲染表单页面和接收提交的完整模型数据:
public class ServicesController : Controller { // 渲染创建服务的表单页面 public IActionResult Create() { // 初始化空的字段列表,避免视图遍历时报空引用错误 return View(new Services { ServiceFields = new List<ServiceFields>() }); } // 接收表单提交的数据并处理 [HttpPost] [ValidateAntiForgeryToken] public IActionResult Create(Services service) { if (ModelState.IsValid) { // 此处添加业务逻辑,比如将数据存入数据库 // _context.Services.Add(service); // _context.SaveChanges(); return RedirectToAction(nameof(Index)); } // 验证失败时返回原视图,保留用户已输入的内容 return View(service); } }
2. 前端视图(含动态添加字段逻辑)
在Views/Services/Create.cshtml中编写表单,结合JavaScript实现动态添加ServiceFields输入控件,严格遵循ASP.NET Core模型绑定的命名规则:
@model Services @{ ViewData["Title"] = "创建服务"; } <h1>创建服务</h1> <form asp-action="Create"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <!-- 服务标题输入框 --> <div class="form-group"> <label asp-for="Title" class="control-label"></label> <input asp-for="Title" class="form-control" /> <span asp-validation-for="Title" class="text-danger"></span> </div> <!-- 服务描述输入框 --> <div class="form-group"> <label asp-for="Description" class="control-label"></label> <textarea asp-for="Description" class="form-control"></textarea> <span asp-validation-for="Description" class="text-danger"></span> </div> <!-- 动态字段容器 --> <div class="form-group"> <h3>服务字段</h3> <div id="serviceFieldsContainer"> <!-- 遍历已存在的字段(初始化空字段或编辑场景的已有字段) --> @for (int i = 0; i < Model.ServiceFields.Count; i++) { <div class="field-group mb-3"> <label asp-for="ServiceFields[i].Title" class="control-label"></label> <input asp-for="ServiceFields[i].Title" class="form-control" /> <span asp-validation-for="ServiceFields[i].Title" class="text-danger"></span> <button type="button" class="btn btn-danger mt-1 remove-field">删除</button> </div> } </div> <button type="button" id="addFieldBtn" class="btn btn-primary mt-2">添加字段</button> </div> <div class="form-group"> <input type="submit" value="保存" class="btn btn-success" /> </div> </form> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} <script> document.addEventListener('DOMContentLoaded', function() { const container = document.getElementById('serviceFieldsContainer'); const addBtn = document.getElementById('addFieldBtn'); // 初始索引值,对应已渲染的字段数量 let fieldIndex = @Model.ServiceFields.Count; // 添加字段按钮逻辑 addBtn.addEventListener('click', function() { // 生成符合模型绑定规则的输入框HTML const fieldHtml = ` <div class="field-group mb-3"> <label for="ServiceFields_${fieldIndex}__Title" class="control-label">字段标题</label> <input type="text" class="form-control" id="ServiceFields_${fieldIndex}__Title" name="ServiceFields[${fieldIndex}].Title" /> <span class="text-danger field-validation-valid" data-valmsg-for="ServiceFields[${fieldIndex}].Title" data-valmsg-replace="true"></span> <button type="button" class="btn btn-danger mt-1 remove-field">删除</button> </div> `; container.insertAdjacentHTML('beforeend', fieldHtml); // 为新添加的删除按钮绑定事件 bindRemoveEvents(); fieldIndex++; }); // 绑定删除字段的事件 function bindRemoveEvents() { document.querySelectorAll('.remove-field').forEach(btn => { btn.addEventListener('click', function() { this.closest('.field-group').remove(); }); }); } // 初始化绑定删除事件 bindRemoveEvents(); }); </script> }
3. 核心注意事项
- 模型绑定规则:动态生成的输入框
name属性必须遵循ServiceFields[N].Title格式(N为从0开始的连续索引),ASP.NET Core才能自动将数据绑定到List<ServiceFields>集合。 - 客户端验证:通过引入
_ValidationScriptsPartial,动态添加的字段也能触发模型验证逻辑(比如必填项校验)。 - 空列表初始化:在Get动作中初始化
ServiceFields为空列表,避免视图遍历集合时出现空引用异常。
内容的提问来源于stack exchange,提问作者Mohaned Ghawar
相关产品推荐
相关产品推荐

