NullReferenceException 和视图模型导航属性
我正在努力寻找一种方法来处理视图模型中的空值。其中一些值是我的模型中的嵌套对象或导航对象。如何在不向视图中引入逻辑的情况下防止视图抛出空引用错误?这看起来很容易,但今天已经结束了。
我有一个带有一些导航属性的视图模型,如下所示:
ViewModel.cs
public class ViewModel
{
public ViewModel () {}
public ViewModel (Contact contact, IDemographicService demographicService)
: this()
{
Id = contact.Id;
Name = contact.Name;
EthnicityId = contact.EthnicityId;
if(EthnicityId > 0 || EthnicityId != null)
Ethnicity = deomographicService.GetEthnicityById((int)contact.EthnicityId);
}
public int Id {get;set;}
public string Name {get;set;}
public int? EthnicityId {get;set;}
public Ethnicity Ethnicity {get;set;}
}
我将跳过控制器,因为这不是我问题的重点。 (我知道逻辑可以放入控制器中,但我选择将其放入 ViewModel 中)。
MyView.cshtml
@model ViewModel
<ul>
<li>@Model.Name</li>
<li>@Model.Ethnicity.Name</>//This is the null reference.
</ul>
我想我可以只定义一个“EthnicityName”字符串(如果为 null,则返回 null)而不是整个对象,但在某些情况下,我需要 Ethnicity 对象中的多个属性。这消除了种族,无论是在视图模型、控制器还是视图中。简而言之,对于 null.null 我该怎么办?难住了。谢谢。
I am struggling to find a way to deal with null values in my view model. Some of these values are nested or navigation objects within my model. How do I keep my view from throwing a null reference error without introducing logic into the view? This seems easy but it is the end of the day.
I have a view model with some navigation properties like so:
ViewModel.cs
public class ViewModel
{
public ViewModel () {}
public ViewModel (Contact contact, IDemographicService demographicService)
: this()
{
Id = contact.Id;
Name = contact.Name;
EthnicityId = contact.EthnicityId;
if(EthnicityId > 0 || EthnicityId != null)
Ethnicity = deomographicService.GetEthnicityById((int)contact.EthnicityId);
}
public int Id {get;set;}
public string Name {get;set;}
public int? EthnicityId {get;set;}
public Ethnicity Ethnicity {get;set;}
}
I'll skip the controller because that is not the focus of my question. (I know that the logic can go in the controller but I chose to put it in the ViewModel).
MyView.cshtml
@model ViewModel
<ul>
<li>@Model.Name</li>
<li>@Model.Ethnicity.Name</>//This is the null reference.
</ul>
I guess I could define only a "EthnicityName" string (and if null return null) instead of an entire object but there are instances where I need more than one property from the Ethnicity object. This eliminates Ethnicity, whether it is in the view model, controller, or view. In short, what do I do about null.null? Stumped. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我不认为添加“逻辑”来理解空值是一件可怕的事情。此类逻辑是底层 .NET 对象模型的一部分;这不是业务逻辑。
不过,您可以为您希望在模型中可见的
Ethnicity
类型的每个属性添加一个属性到模型中:这样视图就无需执行任何操作。
请注意,我认为这种委托是可以的,而不是格式化。我永远不会向模型添加仅用于格式化目的的属性。
I hardly think it's a terrible thing to add "logic" for understanding null values. Such logic is part of the underlying .NET object model; it's not business logic.
Still, you can add one property to the model for each property of the
Ethnicity
type that you want visible in the model:Then the view has no work to do at all.
Note that I think that this sort of delegation is ok, as opposed to formatting. I would never add a property to the model that was only for the purpose of formatting.
这看起来像是一个类设计问题,而不是一个视图/模型问题。您有一个类,声明它将在初始化时提供种族作为其不可变状态的一部分。然而,当您实际创建对象时,您并没有为该类的使用者做出这种保证。我认为 @John Saunders 解决方案是可行的,但我更愿意将默认种族实例实例化为种族类型的静态成员并返回它。该默认值的 Name 属性将返回“未提供”或类似内容的适合语言的答案。
It seems like a class design problem, not a View/Model problem. You have a class that declares that it will provide an Ethnicity as part of its immutable state upon initialization. However, when you actually create the object you aren't making that guarantee for the class's consumers. I think that @John Saunders solution is viable, but I would be more willing to instantiate a Default Ethnicity instance as a static member on the Ethnicity type and return that. The Name property of that default would return a language appropriate answer for "None Supplied" or something like that.
您可能有兴趣在
ViewModel
上实现IDataErrorInfo
接口,因此在那里实现验证逻辑,而不是在属性 getter/setter 上实现。You might be interested in implementing the
IDataErrorInfo
interface on yourViewModel
therefore implementing validation logic there instead of right on the properties getter/setters.