NullReferenceException和视图模型导航属性

问题描述:

我很努力地找到一种方法来处理我的视图模型中的空值。其中一些值是我的模型中的嵌套或导航对象。如何在不将逻辑引入视图的情况下让我的视图抛出空引用错误?这似乎很容易,但它是一天结束。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.null?难住了。谢谢。

我不认为为理解空值添加“逻辑”是一件可怕的事情。这种逻辑是底层.NET对象模型的一部分;这不是商业逻辑。

不过,你可以将一个属性添加到模型为您要在模型中可见的Ethnicity类型的每个属性:

public Ethnicity Ethnicity {get;set;} 
public string EthnicityName { 
    get {return Ethnicity == null ? String.Empty : Ethnicity.Name;} 
    set {if (Ethnicity != null) {Ethnicity.Name = value;}} 
} 
public int EthnicityCode { 
    get {return Ethnicity == null ? 0 : Ethnicity.Code;} 
    set {if (Ethnicity != null) {Ethnicity.Code = value;}} 
} 

然后视图没有工作在所有做。

请注意,我认为这种委派是好的,而不是格式。我永远不会将属性添加到仅用于格式设置的模型中。

+0

谢谢约翰。你的回答是我认为我必须做的。虽然我的示例相当简单,但我的项目包含其他具有大量属性的“嵌套”对象,其中定义每个属性都会影响视图模型的目的。在这种类型的实例中,会创建一个空对象的“else”语句成为verboten?即其他LargeObject = new LargeObject();这样我的视图有@ Model.LargeObject.Property不会抛出null。我讨厌nulls,但我*与他们打交道。 – trevorc 2011-03-05 03:35:29

+0

p.s.我的意思是在视图中使用逻辑 – trevorc 2011-03-05 03:50:21

+0

@name:我不是MVC专家,尽管我已经从关注点分离的角度得到了一般想法。我不认为这是一个单独的问题。我会问_why_的问题,我有那些空值 - 什么是semanatics?他们代表什么样的模型? – 2011-03-07 18:24:29

这似乎是一个类设计问题,而不是视图/模型问题。你有一个类声明它将在初始化时提供一个种族作为其不可变状态的一部分。然而,当你实际创建这个对象时,你并没有为这个类的消费者做出保证。我认为@John Saunders解决方案是可行的,但我更愿意将Default种族实例作为种族类型的静态成员实例化并返回。该默认的名称属性将返回一个语言适当的答案“None Supplied”或类似的东西。

+0

Ritch我得到了你所说的,这是我考虑的事情,但是我的项目的实际情况(我的例子很简单)是我有很大的对象图表,不幸的是,它可以为null。医疗保健索赔遇到拨款作家,并决定他的兄弟公共卫生试点项目更好看。 – trevorc 2011-03-05 03:48:36

+0

区分null和Empty是模型的行为。 – 2011-03-05 03:55:31

+0

但基于我的例子种族不是空的它是空的。我无法控制用户是否选择了种族。因此,Ethnicity.Name == null.null。约翰的上述答案解决了这个问题,除非你有一个拥有很多属性的大对象。 – trevorc 2011-03-05 04:24:45

您可能有兴趣在ViewModel上实现IDataErrorInfo接口,因此在那里实现验证逻辑,而不是属性getter/setters。