ASP.NET Core MVC用户职业信息展示、新增与删除功能问题排查
问题:ASP.NET Core MVC编辑页实现职业信息的展示、新增与删除
需求
- 在ASP.NET Core MVC编辑页面展示用户已录入并存储在数据库的职业信息
- 支持新增职业信息
- 支持删除已有职业信息
现有实现状态
- 控制器:已完成可正常运行的代码,能从数据库获取当前用户的所有职业信息
- 模型:已定义
TutorProfessionAndCost实体类,包含职业相关字段 - 编辑页面:初始版本无法展示已有信息,但通过JS可新增职业控件
- JS代码:已实现点击动态新增职业控件的功能,运行正常
尝试的方案及问题
使用for循环遍历用户职业信息渲染页面,能展示并编辑已有信息,但无法新增新的职业信息
解决方案
核心思路是复用动态新增的JS逻辑渲染已有数据,同时保证表单字段命名符合ASP.NET MVC模型绑定规则(集合格式[index].PropertyName),实现展示、新增、删除的统一交互。
步骤说明
- 统一已有数据与新增数据的DOM结构,确保两者表单字段命名规则一致
- 用Razor循环渲染已有数据,复用JS新增功能的模板结构
- 为每个职业条目添加删除按钮,通过事件委托处理动态元素的删除逻辑
- 保证表单字段命名满足
Professions[@index].XXX格式,让模型绑定正确识别集合数据
完整代码示例
模型代码(TutorProfessionAndCost及视图模型)
// 职业实体类 public class TutorProfessionAndCost { public int Id { get; set; } public string ProfessionName { get; set; } public decimal HourlyCost { get; set; } // 其他职业相关字段 } // 页面视图模型(封装页面所需全部数据) public class TutorEditViewModel { public List<TutorProfessionAndCost> Professions { get; set; } = new List<TutorProfessionAndCost>(); // 其他用户信息字段 }
控制器代码
public IActionResult Edit() { var viewModel = new TutorEditViewModel(); // 从数据库获取当前用户的职业信息(替换为实际查询逻辑) viewModel.Professions = _dbContext.TutorProfessions .Where(t => t.UserId == currentUserId) .ToList(); return View(viewModel); } [HttpPost] public IActionResult Edit(TutorEditViewModel viewModel) { if (ModelState.IsValid) { // 处理职业信息的增删改:删除数据库中不在viewModel里的条目,新增/更新存在的条目 _dbContext.SaveChanges(); return RedirectToAction("Index"); } return View(viewModel); }
视图代码(Edit.cshtml)
@model TutorEditViewModel <form asp-action="Edit" method="post"> <!-- 其他用户信息表单字段 --> <div id="professions-container"> <!-- 渲染已有职业信息 --> @for (int i = 0; i < Model.Professions.Count; i++) { <div class="profession-item mb-3"> <input type="hidden" asp-for="Professions[i].Id" /> <div class="form-group"> <label asp-for="Professions[i].ProfessionName"></label> <input asp-for="Professions[i].ProfessionName" class="form-control" /> <span asp-validation-for="Professions[i].ProfessionName" class="text-danger"></span> </div> <div class="form-group"> <label asp-for="Professions[i].HourlyCost"></label> <input asp-for="Professions[i].HourlyCost" class="form-control" /> <span asp-validation-for="Professions[i].HourlyCost" class="text-danger"></span> </div> <button type="button" class="btn btn-danger delete-profession">删除</button> </div> } </div> <button type="button" id="add-profession" class="btn btn-primary mb-3">新增职业</button> <button type="submit" class="btn btn-success">保存</button> </form> <!-- 新增职业的模板(隐藏,用于JS克隆) --> <script type="text/template" id="profession-template"> <div class="profession-item mb-3"> <input type="hidden" name="Professions[{index}].Id" value="0" /> <div class="form-group"> <label>职业名称</label> <input type="text" name="Professions[{index}].ProfessionName" class="form-control" /> </div> <div class="form-group"> <label>小时费用</label> <input type="number" name="Professions[{index}].HourlyCost" class="form-control" /> </div> <button type="button" class="btn btn-danger delete-profession">删除</button> </div> </script>
JS代码(整合新增与删除逻辑)
$(document).ready(function() { // 新增职业按钮点击事件 $('#add-profession').click(function() { var container = $('#professions-container'); // 用当前条目数量作为新索引 var index = container.children('.profession-item').length; // 克隆模板并替换索引占位符 var template = $('#profession-template').html().replace(/\{index\}/g, index); container.append(template); }); // 删除职业按钮点击事件(事件委托,兼容动态生成的元素) $('#professions-container').on('click', '.delete-profession', function() { $(this).closest('.profession-item').remove(); // 可选:重新调整剩余条目的索引(非必须,ASP.NET Core支持非连续索引) reindexProfessionItems(); }); // 重新索引函数(可选,保证索引连续) function reindexProfessionItems() { $('#professions-container .profession-item').each(function(index) { $(this).find('input, select, textarea').each(function() { var name = $(this).attr('name').replace(/Professions\[\d+\]/, `Professions[${index}]`); $(this).attr('name', name); }); }); } });
关键说明
- 模型绑定兼容性:
Professions[index].PropertyName的命名格式是ASP.NET Core MVC识别集合数据的标准格式,确保表单数据能正确绑定到视图模型的List<TutorProfessionAndCost>属性。 - 模板复用:已有数据和新增数据使用完全一致的DOM结构,保证交互逻辑统一。
- 事件委托:删除按钮使用事件委托绑定,确保动态生成的条目也能触发删除操作。
- 索引灵活性:ASP.NET Core支持非连续索引绑定,若不需要严格连续的索引,可跳过
reindexProfessionItems函数,简化逻辑。
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

