【问题标题】:NullReferenceException and view model navigation propertiesNullReferenceException 和视图模型导航属性
【发布时间】:2011-03-05 01:59:38
【问题描述】:

我正在努力寻找一种方法来处理我的视图模型中的空值。其中一些值是我模型中的嵌套或导航对象。如何在不将逻辑引入视图的情况下防止视图抛出空引用错误?这似乎很容易,但这是一天的结束。

我有一个带有一些导航属性的视图模型,如下所示:

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?难住了。谢谢。

【问题讨论】:

    标签: .net asp.net-mvc-3 view viewmodel


    【解决方案1】:

    我几乎不认为添加“逻辑”来理解空值是一件可怕的事情。这种逻辑是底层 .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;}}
    }
    

    那么视图根本没有工作要做。

    请注意,我认为这种委派是可以的,而不是格式化。我永远不会向模型添加仅用于格式化的属性。

    【讨论】:

    • 谢谢约翰。你的回答与我认为我必须做的事情一致。尽管我的示例相当简单,但我的项目包含其他具有大量属性的“嵌套”对象,其中定义每个属性都违背了视图模型的目的。在这种类型的实例中,创建空对象的“else”语句是否会被禁止?即 else LargeObject = new LargeObject();这样我的具有@Model.LargeObject.Property 的视图就不会抛出空值。我讨厌空值,但我不得不处理它们。
    • 附注我的意思是视图中的逻辑
    • @name:我不是 MVC 专家,尽管我对关注点分离有大致的了解。我不认为这是一个单独的问题。我会问为什么我有那些空值的问题 - 语义是什么?它们对模型代表什么?
    【解决方案2】:

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

    【讨论】:

    • Ritch 我明白你的意思,这是我考虑过的,但我的项目的现实(我的示例很容易发布)是我有大型对象图,不幸的是可以为空。医疗保健索赔与资助作者会面,并决定他的兄弟公共卫生试点项目更好看。
    • 区分 null 和 Empty 是模型的一种行为。
    • 但是根据我的例子 Ethnicity 不是空的,它是空的。如果用户没有选择种族,我无法控制。因此 Ethnicity.Name == null.null。约翰上面的回答解决了这个问题,除非你有一个有很多属性的大对象。
    • 它确实解决了这个问题,但它在 ViewModel 中为 Ethnicity 类中的每个属性创建了一个依赖项。想象一下,如果你有 50 或 100 处房产要在那个庄园里转发。如果您更改其中一个属性的类型怎么办。这种耦合是不必要的,并且使事情变得脆弱。我会添加一个示例,但您似乎对 @John 的回复感到满意,所以我会放手。
    • 我想我没有很好地解释自己。你的最后一条评论准确地描述了我真正的困境。我 100% 同意您所说的 50 或 100 处房产。我想我的问题是:如果 Ethnicity 有 50 个属性可能会或可能不会在视图中查看(@Model.Ethnicity.Property1 等)?那么创建一个空的 Ethnicity 对象以满足视图的 if/else 语句会是不好的做法吗?这是我能想到的唯一解决方案,没有约翰的答案和你描述的依赖关系。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-04
      • 1970-01-01
      • 1970-01-01
      • 2014-03-23
      • 2015-08-02
      • 1970-01-01
      相关资源
      最近更新 更多