Razor视图动态创建SelectList遇空引用错误的技术问询
Razor视图中动态创建SelectList的正确技巧
问题场景
视图模型定义
public class ViewModel { public int SelectedItem {get; set;} public List<Meeting> Meetings {get; set;} } public class Meeting { public int Id {get; set;} public string Title {get; set;} public string Info {get; set;} }
尝试用@Html.DropDownListFor创建size为10的列表框,使用以下方式快速生成SelectList:
@Html.DropDownListFor(model => model.SelectedItem, new SelectList(Model.Meetings, "Meeting.Id", "Meeting.Title"), new {@id="itemList"})
首次加载Meetings为空列表时正常,但填充数据后出现未将对象引用设置到对象实例错误。
后续尝试在控制器中创建SelectList存入ViewBag:
ViewBag.mySelectList = new SelectList(ViewModel.Meetings, "Meeting.Id", "Meeting.Title")
调试可见SelectList已包含数据,但视图仍报相同错误。
仅当手动生成SelectListItem列表再创建SelectList时功能正常:
var selList = Meetings.Select(m => new SelectListItem { Value = m.Id.ToString(), Text = m.Title}).ToList(); mySelectList = new SelectList(selList, "Value", "Text");
问题根源
创建SelectList时指定的dataValueField和dataTextField参数错误。当数据源是List<Meeting>这类实体集合时,这两个参数应该直接写实体的属性名"Id"和"Title",而非"Meeting.Id"和"Meeting.Title"——SelectList会自动遍历集合中的每个Meeting对象,直接访问其属性,不需要额外添加类名前缀。
当Meetings为空时,SelectList不会触发属性解析逻辑,因此不报错;一旦集合有数据,它尝试访问每个对象的Meeting.Id属性,而Meeting类型本身并没有名为Meeting的嵌套属性,最终抛出空引用错误。
正确的动态创建方式
方式1:视图中直接创建
适合简单场景,无需在控制器额外处理:
@Html.DropDownListFor(model => model.SelectedItem, // 处理Meetings为null的情况,避免潜在错误 new SelectList(Model.Meetings ?? new List<Meeting>(), "Id", "Title"), new {@id="itemList", size="10"})
方式2:控制器中创建并存入ViewBag
适合需要在多个视图复用下拉列表的场景:
// 控制器代码 // 确保Meetings不为null var meetings = viewModel.Meetings ?? new List<Meeting>(); ViewBag.mySelectList = new SelectList(meetings, "Id", "Title");
视图中调用:
@Html.DropDownListFor(model => model.SelectedItem, (SelectList)ViewBag.mySelectList, new {@id="itemList", size="10"})
方式3:预生成SelectListItem集合
适合需要对选项做额外处理(如添加默认项、过滤选项)的复杂场景:
// 控制器代码 var selList = (viewModel.Meetings ?? new List<Meeting>()) .Select(m => new SelectListItem { Value = m.Id.ToString(), Text = m.Title }) // 可选:添加默认提示选项 .Prepend(new SelectListItem { Value = "", Text = "-- 选择会议 --" }) .ToList(); // 视图模型中需添加对应的List<SelectListItem>属性 viewModel.MySelectList = selList;
视图中调用:
@Html.DropDownListFor(model => model.SelectedItem, Model.MySelectList, new {@id="itemList", size="10"})
总结
- 当数据源为实体集合时,
SelectList的dataValueField和dataTextField直接写实体的属性名,不要加类名前缀。 - 始终处理集合为
null的情况,避免空引用错误。 - 根据场景选择合适的创建方式:简单场景用视图直接创建,跨视图复用用ViewBag,复杂逻辑用预生成SelectListItem。
内容的提问来源于stack exchange,提问作者Paul Gibson
相关产品推荐
相关产品推荐

