C# ASP.NET MVC中SelectList访问对象嵌套属性显示Location.Name问题
错误原因
- 空引用报错的核心诱因有两个:
nameof(Shop.Location.Name)最终生成的字符串为"Name",而非你预期的嵌套路径"Location.Name",SelectList无法自动解析嵌套属性层级,会直接在Shop实例上查找名为Name的属性,查找失败就会触发异常- 若数据库中存在
Location为null的Shop记录,直接访问Location.Name也会触发空引用
- 绑定
Shop.Location后显示类名的原因:SelectList会对文本字段对应的对象调用默认ToString()方法,未重写的情况下默认输出类的全限定名。
解决方案
方案1:查询时投影为扁平化匿名类(最推荐,无侵入、性能最优)
无需修改实体类,查询时直接把需要的字段展开为平级属性,同时可以提前过滤无效数据:
var shops = _applicationDbContext.Shops .Where(x => x.Location != null) // 过滤无位置的门店,避免空引用 .Select(x => new { Id = x.Id, LocationName = x.Location.Name }) .ToList(); var mwc = new Create { ShopSL = new SelectList(shops, nameof(Id), nameof(LocationName)) };
方案2:Shop类新增只读包装属性(适合多处需要调用门店位置名称的场景)
在Shop实体类中新增一个封装了嵌套属性访问的只读属性,自带空值判断:
public class Shop { public int Id { get; set; } public Location Location { get; set; } // 新增只读属性 public string LocationName => Location?.Name ?? "无位置信息"; }
绑定直接使用新增的属性即可:
var shops = _applicationDbContext.Shops .Include(x => x.Location) .ToList(); var mwc = new Create { ShopSL = new SelectList(shops, nameof(Shop.Id), nameof(Shop.LocationName)) };
方案3:重写Location类的ToString方法(适合全局需要展示Location名称的场景)
如果业务中所有展示Location的场景都默认显示Name,可以重写ToString方法:
public class Location { public int Id { get; set; } public string Name { get; set; } public override string ToString() { return Name ?? string.Empty; } }
绑定直接使用Location作为文本字段即可,SelectList会自动调用ToString方法输出名称:
var mwc = new Create { ShopSL = new SelectList(shops, nameof(Shop.Id), nameof(Shop.Location)) };
内容的提问来源于stack exchange,提问作者Vincensiu
相关产品推荐
相关产品推荐

