Shielding nullable domain properties with ViewMode

2019-04-01 00:18发布

问题:

I am using Entity Framework 4.0, and making use of POCO objects. When I populate POCO objects from the DB, I translate property values to my own Domain objects, which we can call my Model.

Necessarily, whether or not the fields of my Model are Nullable depends on whether the value it maps to in the database comes from a NULL or NOT NULL column. I won't go into detail, but the values must be nullable in the DB, because a user can partially save a draft of the object before publishing it to the public. That being the case, I have several fields that are nullable. So let's say my model looks like:

public class MyModel
{
   public int? Field1 {get; set; }
   public DateTime? Field2 {get; set; }
   public int Field3 {get; set; }
}

If I use this Model in my View, complete with nullable fields, I begin receiving errors that tell me I cannot use nullable properties as values in various places, like HTML helpers, etc. I could say something like if (Model.MyBoolField.HasValue && Model.MyBoolField.Value) { // etc }, but that feels bulky for a view.

I considered creating a ViewModel object that inherits from my original domain object and has new, non-nullable versions of my nullable fields that return an appropriate value if the base version is null. So something like:

public class MyViewModel : MyModel
{
   public new int Field1
   {
      get { return base.Field1 ?? 7; }
   }

   public new DateTime Field2
   {
      get { return base.Field2 ?? DateTime.Now; }
   }
}

My problem with this is that I don't always know a good "default" value to display. What if I threw an exception in the View Model's getter when the base value is null? Is that poor practice?

I'm basically looking for a best practice on how to handle nullable fields in a model, particularly when displaying in a View.

回答1:

If you just need to display these fields in a View, you don't need to specify or check whether is has a value or not.

Using Model.Field1 in your View file is enough. It will simple not display anything, and it won't throw an exception. You can always use ?? to set a default when it makes sense.

@(Model.Field1 ?? "There is nothing to see here")


回答2:

In most of the cases I use the "For" helpers, which seem OK with Nullable values (PublishedCount is a nullable property):

@Html.TextBoxFor(m => m.BillPull.PublishedCount, new { id="txtPublishedCount" })
@Html.ValidationMessageFor(m => m.BillPull.PublishedCount)

When I need to use just TextBox, I use the GetValueOrDefault method, with whatever default value the framework provides:

@Html.TextBox("BillPull.AutoPublishDate", Model.BillPull.AutoPublishDate.GetValueOrDefault().ToString(dateFormat), new { id = "dtpAutoPublishDate" })
@Html.ValidationMessageFor(m => m.BillPull.AutoPublishDate)