Reputation: 3031
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
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
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
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