ASP.NET MVC级联下拉框选项显示undefined问题求助
级联下拉框选项显示undefined问题修复
问题场景
在表单中实现位置-房间二级联动下拉:
- 位置下拉框选中项变化时,通过ajax请求后端接口拉取对应位置的房间列表
- 接口可正常返回预期数量的选项数据,但渲染后所有选项文本显示为
undefined
原视图核心代码
<div class="form-group row"> <div class="col-4"> <label asp-for="job.LocationId"></label> </div> <div class="col-8"> <select asp-for="job.LocationId" id="LocationId" name="LocationId" asp-items="@Model.LocationList" class="form-select"> <option disabled selected>--Select Location--</option> </select> </div> </div> <div class="form-group row"> <div class="col-4"> <label asp-for="job.RoomId"></label> </div> <div class="col-8"> <select id="RoomId" name="RoomId" asp-for="job.RoomId" asp-items="@(new SelectList(string.Empty, "Value", "Text"))" class="form-select"> </select> </div> </div>
原前端联动JS代码
<script> $(document).ready(function () { $('#LocationId').change(function () { $("#RoomId").empty(); $.ajax({ type: 'GET', url: '@Url.Action("GetRooms")', dataType: 'json', data: { locationId: $('#LocationId Option:Selected').val() }, success: function (rooms) { $.each(rooms, function (i, room) { $("#RoomId").append('<option value="' + room.Value + '">' + room.Text + '</option>'); }); }, error: function (ex) { alert('Failed to retrieve rooms.' + ex); } }); return false; }) }); </script>
原后端接口代码
[HttpGet] public JsonResult GetRooms(string locationId) { int.TryParse(locationId, out int LocID); List<SelectListItem> rooms = new List<SelectListItem>(); rooms.Add(new SelectListItem { Text = "-- Select Room --", Value = "0" }); IEnumerable<Room> roomList = _unitOfWork.Room.GetAll(r => r.LocationId == LocID); foreach (Room room in roomList) { rooms.Add(new SelectListItem { Text = room.RoomName, Value = room.Id.ToString() }); } var list = Json(new SelectList(rooms, "Value", "Text")); return Json(new SelectList(rooms, "Value", "Text")); }
问题根因
ASP.NET Core 默认的JSON序列化规则会将C#端的帕斯卡命名(首字母大写,如Text/Value)自动转换为驼峰命名(首字母小写,如text/value)返回给前端。前端代码中读取的是大写开头的room.Value、room.Text,实际返回的JSON对象中不存在这两个属性,取值为undefined,最终渲染出的选项文本就显示为undefined。
另外原代码中存在两处冗余/不规范点:
- 后端接口中定义了未使用的变量
list,属于冗余代码 - 前端选择选中项的选择器写为
Option:Selected,不符合jQuery选择器规范,应写为小写的option:selected
修复方案
二选一即可,推荐优先选方案1,改动量最小。
方案1:修改前端JS属性读取逻辑
将success回调中读取选项属性的代码改为读取小写开头的属性即可,修正后的JS代码:
<script> $(document).ready(function () { $('#LocationId').change(function () { $("#RoomId").empty(); $.ajax({ type: 'GET', url: '@Url.Action("GetRooms")', dataType: 'json', data: { locationId: $('#LocationId option:selected').val() }, success: function (rooms) { $.each(rooms, function (i, room) { // 改为读取小写开头的value、text属性 $("#RoomId").append('<option value="' + room.value + '">' + room.text + '</option>'); }); // 可选:加载完成后默认选中第一个提示项 $("#RoomId").val("0"); }, error: function (ex) { alert('获取房间列表失败:' + ex.responseText); } }); return false; }) }); </script>
方案2:修改后端返回逻辑,避免序列化命名问题
后端不需要将列表二次包装为SelectList类型,直接返回构造好的简单对象列表即可,同时删除冗余代码,修正后的接口代码:
[HttpGet] public JsonResult GetRooms(string locationId) { int.TryParse(locationId, out int LocID); List<object> rooms = new List<object> { new { Text = "-- Select Room --", Value = "0" } }; IEnumerable<Room> roomList = _unitOfWork.Room.GetAll(r => r.LocationId == LocID); foreach (Room room in roomList) { rooms.Add(new { Text = room.RoomName, Value = room.Id.ToString() }); } // 直接返回列表,删除冗余的SelectList包装和无用变量 return Json(rooms); }
内容的提问来源于stack exchange,提问作者Frostie8467
相关产品推荐
相关产品推荐

