级联DropDownList已实现,选中值无法更新数据库的解决方法
问题诊断与修复方案
1. 修复JavaScript的HTML拼接错误
你的级联下拉框JS代码中,拼接<option>标签时误用了HTML转义字符",导致生成的选项value属性被错误追加无效字符(比如原本应为value="1",实际变成value="1""),提交时模型绑定无法识别这个无效数值,直接导致StoreWid无法正确赋值。
修改后的JS代码:
<script> $('#AmmoWid').change(function () { $('#StoreWid').empty(); $.ajax({ url: "@Url.Action("GetStore")", type: "Get", data: { id: $('#AmmoWid option:selected').val() }, dataType: "json", success: function (result) { $.each(result, function (i, Store) { // 修正引号拼接逻辑,直接使用双引号转义 $('#StoreWid').append('<option value="' + Store.value + '">' + Store.text + '</option>'); }) } }) }) </script>
2. 对齐表单字段与模型绑定的名称
从你的View代码(比如@Html.LabelFor(model => model.TblUsed.DateWid))能看出,View的模型是一个包含TblUsed属性的父ViewModel,但Post方法直接接收TblUsed类型参数,导致表单提交的字段名(如TblUsed.StoreWid)和模型绑定预期的字段名(StoreWid)不匹配,这也是绑定失败的核心原因之一。
解决方式二选一:
方式A:修改Post方法接收ViewModel
如果你的View使用的是包含TblUsed的ViewModel(比如CreateUsedViewModel),调整Post方法如下:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("TblUsed.RowWid,TblUsed.DateWid,TblUsed.AmmoWid,TblUsed.QtyUsed,TblUsed.StoreWid")] CreateUsedViewModel vm) { if (ModelState.IsValid) { _context.Add(vm.TblUsed); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } // 验证失败后重新填充下拉选项,避免页面下拉框为空 var strRowWid = "RowWid"; var strDt = "Dt"; var dateNow = DateOnly.FromDateTime(DateTime.Now); ViewBag.DateWid = new SelectList(_context.TblDays.OrderByDescending(x => x.Dt).Where(n => n.Dt <= dateNow), strRowWid, strDt); ViewBag.ammo = _context.VwAmmos.OrderBy(n => n.Caliber) .Select(n => new SelectListItem { Value = n.RowWid.ToString(), Text = $"{n.WeaponType} {n.Caliber} {n.Brand} {n.Style}", }).ToList(); return View(vm); }
方式B:调整表单字段名称匹配模型
改用强类型辅助方法生成下拉框,自动对齐字段名称:
<div class="form-group"> @Html.LabelFor(model => model.TblUsed.DateWid, htmlAttributes: new { @class = "control-label"}) <div> @Html.DropDownListFor(model => model.TblUsed.DateWid, ViewBag.DateWid as SelectList, "--select date--", new { @class = "form-control form-select-sm form-select" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.TblUsed.AmmoWid, htmlAttributes: new { @class = "control-label"}) <div> @Html.DropDownListFor(model => model.TblUsed.AmmoWid, ViewBag.ammo as List<SelectListItem>, "--select Ammo--", new { @class = "form-control form-select-sm form-select" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.TblUsed.StoreWid, htmlAttributes: new { @class = "control-label"}) <div> @Html.DropDownListFor(model => model.TblUsed.StoreWid, new SelectList(Enumerable.Empty<SelectListItem>()), "--select Store--", new { @class = "form-control form-select-sm form-select" }) </div> </div>
同时修改Post方法的Bind属性,添加前缀匹配:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind(Prefix = "TblUsed", Include = "RowWid,DateWid,AmmoWid,QtyUsed,StoreWid")] TblUsed tblUsed) { if (ModelState.IsValid) { _context.Add(tblUsed); await _context.SaveChangesAsync(); return RedirectToAction(nameof(Index)); } // 重新填充下拉选项 var strRowWid = "RowWid"; var strDt = "Dt"; var dateNow = DateOnly.FromDateTime(DateTime.Now); ViewBag.DateWid = new SelectList(_context.TblDays.OrderByDescending(x => x.Dt).Where(n => n.Dt <= dateNow), strRowWid, strDt); ViewBag.ammo = _context.VwAmmos.OrderBy(n => n.Caliber) .Select(n => new SelectListItem { Value = n.RowWid.ToString(), Text = $"{n.WeaponType} {n.Caliber} {n.Brand} {n.Style}", }).ToList(); // 根据View的模型结构返回对应数据,示例为包含TblUsed的匿名对象 return View(new { TblUsed = tblUsed }); }
3. 验证失败后重新填充下拉选项
当Post方法因验证失败返回View时,必须重新填充ViewBag中的下拉选项,否则页面上的下拉框会变为空,影响用户再次提交。上述代码已包含该逻辑。
内容的提问来源于stack exchange,提问作者user3536476
相关产品推荐
相关产品推荐

