ASP.NET Razor Pages+PostgreSQL级联下拉列表实现求助
解决ASP.NET Razor Pages + PostgreSQL的级联下拉列表问题
看起来你现在的核心问题是第二个下拉框没有根据第一个选中的地点动态过滤房间,而是一次性加载了所有数据。咱们一步步来修改代码实现级联效果:
一、重构后台逻辑,添加动态查询端点
首先需要在你的PageModel里新增一个处理GET请求的方法,用来根据选中的地点返回对应的房间列表,同时优化现有数据库查询的写法:
// 保留原有加载地点列表的方法(简化嵌套的using块) public List<WorkspaceModel> PopulateReservations() { var cs = Database.Database.Connector(); var locations = new List<WorkspaceModel>(); using var con = new NpgsqlConnection(cs); con.Open(); const string query = "SELECT DISTINCT location FROM workspaces"; using var cmd = new NpgsqlCommand(query, con); using var dr = cmd.ExecuteReader(); while (dr.Read()) { locations.Add(new WorkspaceModel { LocationName = dr["location"].ToString() }); } return locations; } // 新增:根据地点动态获取房间的Handler方法 public IActionResult OnGetRoomsByLocation(string location) { if (string.IsNullOrEmpty(location)) { return new JsonResult(new List<WorkspaceModel>()); } var cs = Database.Database.Connector(); var rooms = new List<WorkspaceModel>(); using var con = new NpgsqlConnection(cs); con.Open(); // 用参数化查询避免SQL注入风险 const string query = "SELECT room FROM workspaces WHERE location = @location"; using var cmd = new NpgsqlCommand(query, con); cmd.Parameters.AddWithValue("@location", location); using var dr = cmd.ExecuteReader(); while (dr.Read()) { rooms.Add(new WorkspaceModel { RoomName = dr["room"].ToString() }); } return new JsonResult(rooms); }
二、修改前端HTML,添加动态更新的JavaScript
现在需要调整下拉框的渲染逻辑,并且添加JS监听地点选择事件,异步请求后台数据更新房间列表:
修改后的HTML代码
<td>Select location</td> <div class="form-group"> <select id="locations" name="Location"> <option value="">--请选择地点--</option> @foreach(var item in Model.PopulateReservations()) { <!-- 给option加上value属性,方便JS获取选中值 --> <option value="@item.LocationName">@Html.DisplayFor(m => item.LocationName)</option> } </select> </div> <td>Select Room</td> <div class="form-group"> <select id="rooms" name="Room"> <option value="">--请先选择地点--</option> </select> </div>
添加JavaScript逻辑(放在页面底部或单独JS文件)
<script> document.addEventListener('DOMContentLoaded', function() { const locationSelect = document.getElementById('locations'); const roomSelect = document.getElementById('rooms'); // 监听地点下拉框的选择变化 locationSelect.addEventListener('change', async function() { const selectedLocation = this.value; roomSelect.innerHTML = '<option value="">--加载中--</option>'; // 如果没有选中地点,重置房间下拉框 if (!selectedLocation) { roomSelect.innerHTML = '<option value="">--请先选择地点--</option>'; return; } try { // 发送请求到后台的Handler方法 const response = await fetch(`?handler=RoomsByLocation&location=${encodeURIComponent(selectedLocation)}`); if (!response.ok) throw new Error('请求失败'); const rooms = await response.json(); // 清空并重新渲染房间选项 roomSelect.innerHTML = '<option value="">--选择房间--</option>'; rooms.forEach(room => { const option = document.createElement('option'); option.value = room.roomName; option.textContent = room.roomName; roomSelect.appendChild(option); }); } catch (error) { roomSelect.innerHTML = '<option value="">--加载失败,请重试--</option>'; console.error('加载房间列表出错:', error); } }); }); </script>
三、模型类无需额外修改
你的WorkspaceModel已经包含了LocationName和RoomName属性,完全满足当前需求,不需要调整。
关键注意事项
- 参数化查询:一定要用参数化查询替代字符串拼接,避免SQL注入漏洞。
- Razor Pages Handler约定:
OnGetRoomsByLocation对应的请求地址是?handler=RoomsByLocation,这是Razor Pages的固定命名规则。 - URL编码:用
encodeURIComponent处理地点参数,避免特殊字符导致的请求错误。
这样修改后,当你选择第一个下拉框的地点时,第二个下拉框就会自动加载对应地点的房间列表了。
内容的提问来源于stack exchange,提问作者anonD
相关产品推荐
相关产品推荐

