trevorc
trevorc

Reputation: 3031

NullReferenceException and view model navigation properties

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.

Upvotes: 0

Views: 651

Answers (3)

Nano Taboada
Nano Taboada

Reputation: 4182

You might be interested in implementing the IDataErrorInfo interface on your ViewModel therefore implementing validation logic there instead of right on the properties getter/setters.

Upvotes: 0

Ritch Melton
Ritch Melton

Reputation: 11608

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.

Upvotes: 1

John Saunders
John Saunders

Reputation: 161821

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:

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;}}
}

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.

Upvotes: 1

Related Questions