ASP.NET中按用户角色加载asp-items下拉列表并存Session的空值问题
问题根因
下拉框始终为空是三个核心错误导致的:
Selection属性声明后从未初始化,默认值为null。直接调用Selection.Add()时会触发空引用异常,若项目未配置显式异常捕获,会静默失败,Selection始终是无内容的空引用,自然无法给asp-items提供绑定数据。- Session存储逻辑完全失效:仅在权限值为10的分支中尝试拼接选项内容,其余权限分支完全没有写入选项的逻辑;且所有分支执行到最后,都会把
UserRoleMessage覆盖为纯数字的权限值,之前写入的选项内容会被直接覆盖。另外直接用string.Join拼接SelectListItem对象,只会得到类型全名字符串,完全不包含选项的Value、Text信息,存了也无法复用。 - 缺少跨请求重绑逻辑:Razor Pages不会自动在回发请求中保留SelectList数据,表单提交后如果没有重新填充
Selection就返回页面,绑定源会直接为空。
正确实现步骤
1. 初始化集合属性,修正权限判断逻辑
声明属性时直接初始化集合,从根源避免空引用,同时将独立的if判断改为else if互斥逻辑,避免后续权限值调整时出现重复添加选项的问题:
// 初始化集合,杜绝空引用 public List<SelectListItem> Selection { get; set; } = new List<SelectListItem>(); // 绑定下拉框选中值的属性 public string SelectedRole { get; set; } public string UserRoleMessage { get; set; }
2. 修正后端加载与Session存储逻辑
每次加载选项前先清空历史数据,存储选项时用JSON序列化保证数据完整,不要直接拼接对象:
public IActionResult OnGetRecht() { // 清空历史选项,避免重复添加 Selection.Clear(); // 按权限等级加载对应选项 if (UserModel.RECHT == 50) { Selection.AddRange(new [] { new SelectListItem { Value = "SY", Text = "System" }, new SelectListItem { Value = "AD", Text = "Admin" }, new SelectListItem { Value = "ID", Text = "Innendienst" }, new SelectListItem { Value = "SP", Text = "Spediteur" }, new SelectListItem { Value = "DS", Text = "Disponent" } }); } else if (UserModel.RECHT == 40) { Selection.AddRange(new [] { new SelectListItem { Value = "AD", Text = "Admin" }, new SelectListItem { Value = "ID", Text = "Innendienst" }, new SelectListItem { Value = "SP", Text = "Spediteur" }, new SelectListItem { Value = "DS", Text = "Disponent" } }); } else if (UserModel.RECHT == 30) { Selection.AddRange(new [] { new SelectListItem { Value = "ID", Text = "Innendienst" }, new SelectListItem { Value = "SP", Text = "Spediteur" }, new SelectListItem { Value = "DS", Text = "Disponent" } }); } else if (UserModel.RECHT == 20) { Selection.AddRange(new [] { new SelectListItem { Value = "SP", Text = "Spediteur" }, new SelectListItem { Value = "DS", Text = "Disponent" } }); } else if (UserModel.RECHT == 10) { Selection.Add(new SelectListItem { Value = "DS", Text = "Disponent" }); } // 序列化选项列表存入Session,保证数据可复用 var optionsJson = System.Text.Json.JsonSerializer.Serialize(Selection); HttpContext.Session.SetString("UserRoleOptions", optionsJson); // 单独存储用户权限标识 UserRoleMessage = UserModel.RECHT.ToString(); HttpContext.Session.SetString("UserRoleMessage", UserRoleMessage); return Page(); }
3. 前端绑定配置
在cshtml页面中按下述方式绑定下拉框,注意添加默认空选项提升可用性:
<select asp-for="SelectedRole" asp-items="Model.Selection" class="form-control"> <option value="">请选择对应角色</option> </select>
注意事项:如果页面存在POST提交处理逻辑,在调用
return Page()返回视图前,必须重新执行一次选项填充逻辑(可以直接从Session反序列化之前存储的选项数据赋值给Selection,不需要重复判断权限),否则回发后下拉框会再次因绑定源为空不显示内容。
附:Session读取复用方法
其他页面/处理方法需要用到这套角色选项时,直接从Session反序列化即可:
private void PopulateSelectionFromSession() { var sessionData = HttpContext.Session.GetString("UserRoleOptions"); if (!string.IsNullOrWhiteSpace(sessionData)) { Selection = System.Text.Json.JsonSerializer.Deserialize<List<SelectListItem>>(sessionData); } }
内容的提问来源于stack exchange,提问作者Mariam Bari
相关产品推荐
相关产品推荐

