如何从JS视图向ASP.NET MVC Action传递多选列表数据
ASP.NET MVC前端选中列表数据传递为空问题修复
问题背景
在ASP.NET MVC项目中,通过前端JS维护选中的作者、出版社、译者列表(已实现重复项校验、删除后可重新添加功能),尝试通过隐藏输入框将数据传递到后端Create Action,但后端始终接收为空值。
问题原因分析
- Form字段大小写不匹配:后端获取表单数据时使用
Request.Form["selectedAuthors"](小写开头),而前端隐藏输入框的name属性是SelectedAuthors(大写S),ASP.NET表单字段名区分大小写,导致无法获取值。 - JS变量遮蔽问题:
updateHiddenFields函数内重新声明了与全局变量同名的局部变量,导致全局数组的内容没有被正确拼接赋值给隐藏输入框。 - 删除操作的数组更新失效:删除按钮的事件处理中,修改的是局部的
selectedItemList变量,没有同步更新全局数组,导致隐藏输入框的值无法正确反映最新选中状态。
修复方案
1. 后端代码修改
修正Form字段名大小写,与前端保持一致,同时优化空值处理逻辑:
[HttpPost] public async Task<ActionResult> Create(CreateBookViewModel model) { var bookCategory = await _bookCategoryService.GetById(model.CategoryId); // 修正字段名大小写,与前端name属性一致 var selectedAuthors = Request.Form["SelectedAuthors"].ToString(); var selectedPublishers = Request.Form["SelectedPublishers"].ToString(); var selectedTranslators = Request.Form["SelectedTranslators"].ToString(); model.Category = bookCategory.Name; // 处理空字符串,避免Split产生空元素 model.Authors = string.IsNullOrEmpty(selectedAuthors) ? new List<string>() : selectedAuthors.Split(',').ToList(); model.Publishers = string.IsNullOrEmpty(selectedPublishers) ? new List<string>() : selectedPublishers.Split(',').ToList(); model.Translators = string.IsNullOrEmpty(selectedTranslators) ? new List<string>() : selectedTranslators.Split(',').ToList(); if (ModelState.IsValid) { var result = await _bookService.Create(model); if (result.IsSucceeded) { return RedirectToAction("Index", result); } else { ModelState.AddModelError(string.Empty, "خطا در ایجاد کتاب."); } } // 返回原视图保留用户输入,而非重定向清空内容 return View(model); }
2. HTML代码优化
确保所有表单元素包裹在<form>标签内,明确POST请求目标:
<form asp-action="Create" method="post"> <div class="form-group"> <label class="control-label">Authors:</label> <select class="form-control" id="authorInput" asp-items='new SelectList(Model.Authors,"Name")'> <option value="">Select Author</option> </select> <button type="button" id="addAuthorButton" class="btn btn-primary">Add</button> <ul id="selectedAuthorsList" class="list-group"> <!-- 选中项将动态添加到这里 --> </ul> <span id="duplicateAuthorError" class="text-danger"></span> </div> <div class="form-group"> <label class="control-label">Publishers:</label> <select class="form-control" id="publisherInput" asp-items='new SelectList(Model.Publishers,"Name")'> <option value="">Select Publisher</option> </select> <button type="button" id="addPublisherButton" class="btn btn-primary">Add</button> <ul id="selectedPublishersList" class="list-group"> <!-- 选中项将动态添加到这里 --> </ul> <span id="duplicatePublisherError" class="text-danger"></span> </div> <div class="form-group"> <label class="control-label">Translators:</label> <select class="form-control" id="translatorInput" asp-items='new SelectList(Model.Translators,"Name")'> <option value="">Select Translator</option> </select> <button type="button" id="addTranslatorButton" class="btn btn-primary">Add</button> <ul id="selectedTranslatorsList" class="list-group"> <!-- 选中项将动态添加到这里 --> </ul> <span id="duplicateTranslatorError" class="text-danger"></span> </div> <input type="hidden" name="SelectedAuthors" id="SelectedAuthors" /> <input type="hidden" name="SelectedPublishers" id="SelectedPublishers" /> <input type="hidden" name="SelectedTranslators" id="SelectedTranslators" /> <button type="submit" class="btn btn-primary">Save</button> <a class="btn btn-secondary" asp-action="Index">Back To Book List</a> </form>
3. JS代码修复
解决变量遮蔽和删除操作的数组同步问题:
var selectedAuthors = []; var selectedTranslators = []; var selectedPublishers = []; function initializeSelectionLists() { selectedAuthors = []; selectedTranslators = []; selectedPublishers = []; } function isDuplicate(itemName, selectedItemList) { return selectedItemList.includes(itemName); } function addToSelectedList(inputId, listId, errorId, globalList) { var input = document.getElementById(inputId); var inputValue = input.value.trim(); if (inputValue !== "") { if (!isDuplicate(inputValue, globalList)) { var selectedList = document.getElementById(listId); var listItem = document.createElement("li"); listItem.className = "list-group-item"; listItem.textContent = inputValue; var removeButton = document.createElement("button"); removeButton.className = "btn btn-danger btn-sm float-left"; removeButton.textContent = "Delete"; // 直接操作全局数组,确保同步更新 removeButton.onclick = function () { const index = globalList.indexOf(inputValue); if (index !== -1) { globalList.splice(index, 1); } selectedList.removeChild(listItem); updateHiddenFields(); }; listItem.appendChild(removeButton); globalList.push(inputValue); selectedList.appendChild(listItem); input.value = ""; document.getElementById(errorId).textContent = ""; updateHiddenFields(); } else { document.getElementById(errorId).textContent = "duplicate"; } } } // 移除局部变量声明,直接使用全局数组拼接 function updateHiddenFields() { var authorsStr = selectedAuthors.join(","); var publishersStr = selectedPublishers.join(","); var translatorsStr = selectedTranslators.join(","); console.log("SelectedAuthors: " + authorsStr); console.log("SelectedPublishers: " + publishersStr); console.log("SelectedTranslators: " + translatorsStr); document.getElementById("SelectedAuthors").value = authorsStr; document.getElementById("SelectedPublishers").value = publishersStr; document.getElementById("SelectedTranslators").value = translatorsStr; } // 绑定事件时传入对应全局数组 document.getElementById("addAuthorButton").addEventListener("click", function () { addToSelectedList("authorInput", "selectedAuthorsList", "duplicateAuthorError", selectedAuthors); }); document.getElementById("addTranslatorButton").addEventListener("click", function () { addToSelectedList("translatorInput", "selectedTranslatorsList", "duplicateTranslatorError", selectedTranslators); }); document.getElementById("addPublisherButton").addEventListener("click", function () { addToSelectedList("publisherInput", "selectedPublishersList", "duplicatePublisherError", selectedPublishers); });
验证方法
- 打开浏览器开发者工具(F12),切换到Console标签页,添加/删除列表项时查看输出的字符串是否正确。
- 在后端Create Action中设置断点,查看
Request.Form["SelectedAuthors"]等字段是否获取到正确的值。 - 提交表单后,检查ViewModel中的Authors、Publishers、Translators属性是否正确赋值。
内容的提问来源于stack exchange,提问作者Mardibak
相关产品推荐
相关产品推荐

