MVC map to nullable bool in model
Asked Answered
O

6

13

With a view model containing the field:

public bool? IsDefault { get; set; }

I get an error when trying to map in the view:

<%= Html.CheckBoxFor(model => model.IsDefault) %>

Cannot implicitly convert type 'bool?' to 'bool'. An explicit conversion exists (are you missing a cast?)

I've tried casting, and using .Value and neither worked.

Note the behaviour I would like is that submitting the form should set IsDefault in the model to true or false. A value of null simply means that the model has not been populated.

Olivaolivaceous answered 14/6, 2010 at 8:52 Comment(2)
Why would you need to check whether the model has been populated? Maybe there is another way, a right way, to do what you need to do?Slipon
possible duplicate of Why is CheckBoxFor producing runtime errorMaiden
K
15

The issue is you really have three possible values; true, false and null, so the the CheckBoxFor cannot handle the three states (only two states).

Brad Wilson discusses on his blog here. He uses a DropDownList for nullable booleans.

This StackOverflow question does a much better job of describing the situation than I did above. The downside to the solution is sometimes nullable does not imply false, it should be nullable. An example of this would be filter criteria where you don't want true or false applied.

Kilby answered 16/6, 2010 at 11:51 Comment(0)
I
8

If you don't care about the null value, and just want the checkbox to be unchecked when its null, you can do the following:

Create another property of type bool in your Model like this:

public bool NotNullableBool
{
    get
    {
        return NullableBool == true;
    }
    set
    {
        NullableBool = value;
    }
}

Then just use that for binding...

Ilbert answered 25/5, 2012 at 12:32 Comment(2)
get { return NullableBool == true; } *FIFYHighwayman
This worked a treat for me, then binding my CheckboxFor to my NotNullableBoolVani
S
4

To me, this is a lot better:

<%= Html.CheckBox("IsDefault", Model.IsDefault.HasValue? Model.IsDefault : false) %>
Suzan answered 25/10, 2014 at 2:59 Comment(11)
This is fine for True / False, but if you want to handle a real bool?, you need to handle Null also (Think of this as Yes, No, and Unknown.)Glidebomb
It does handle null because Model.IsDefault.HasValue will be checked, found to be null, and give false as a result. Generally we don't care if something is 'null' in our 'true/false' variables --- we just want to know when something is true/met.Suzan
Often this is true. But sometimes people want to know the different between known true, known false, and just unsupplied/unknown. We have fields like Married. But we want to known that they are indeed chosen as married, or chosen as not married, or if the data wasn't entered. If multiple people handle the record, then the next might ask the question if it was never asked. But if you just show it as false, people would assume it was asked and returned as false.Glidebomb
"Generally we don't care"... who is 'we'? Don't talk for others. When designing a database in a commercial environment you need to know if fields are mandatory or not. If not, then NULL is a perfectly valid value and commonly used. If you haven't asked the question and you write code that will set it to false, then you are making an assumption. Greg is correct, there are many occasions when we want to know if a value was filled in or not, and NULL tells us no response was made. I have this exact situation right now where NULL tells the business was not responded to. You cant assume.Loafer
@MarkWorrall "We" was my development team & our customers, since we had their requirements in hand. You would see in the above code, if Model.IsDefault.HasValue does not have a value, it would be false. Shouldn't you only care about the "positive" match, and if it is not that, or doesn't match anything, then you know it's not the "positive" side? To use Greg's "married" example-the person is either married, or they are not. If they are not, or didn't enter data, who cares? We'd just them as if they aren't married. If you need to know individual statuses, you need a radio button, not a T/F.Suzan
*just treat them as ifSuzan
@Suzan False indicates the person was asked whether they were married or not and they said "no". Null indicates the person was never asked the question. There is a huge difference. In the medical field, if a person has a surgery, some pre-surgical or diagnostic questions are irrelevant so any questionnaire they answer will have some N/A (null) values.Rangy
@Wade I don't think you can say "Null indicates the person was never asked the question" because they saw it on the form! If you need an "N/A" option, again, you need a radio button and it be made required to answer it, not a T/F.Suzan
I know this is a lost cause trying to educate someone who has firmly gotten themselves attached to a position but you are making a lot of junior developer mistakes by making so many assumptions: How about null indicates they did not answer the question? Also, you cannot assume the person "saw it on the form" because the data exists independently of a "form". There could be a transfer of data from another system where the bool is completely missing. Is that true, false, "not applicable", or null? What does each represent? I won't respond again so feel free to have the last word.Rangy
@Wade, it's a "junior developer" mistake to not attach validation to a field and make it required in the first place. If it is required and they click "Submit", they will have to answer it before it will proceed - if you do your validation correctly onsubmit. So yes, we CAN assume they saw it in that case, and will be REQUIRED to enter the value. When you are talking about this "data [that] exists independently of a 'form'", and you're going into data being transferred between systems - all of that has absolutely nothing to do w/the control we're talking about that you have control over.Suzan
@Wade - the only valid point you have is if you are taking in data and you don't know its state - such as data between systems you have no control over. That's totally irrelevant here because we have control over this control on this form and our data that's getting stored in our brand-new, single-purposed system. It would only be relevant if we're talking about legacy data that has mistakes that we're injecting into our system, or from other systems (as you mentioned), which would bypass the form and this validationSuzan
A
1

Here's how to map a bullable boolean bool? property in a DropDownListFor:

@model SomeModel

<!-- ...some HTML... -->

@Html.DropDownListFor(m => m.NullableBooleanProperty, new SelectList(
        new[] { 
            new { Value = "", Text = "-- Choose YES or NO --" },
            new { Value = "true", Text = "YES" },
            new { Value = "false", Text = "NO" },
        },
        "Value",
        "Text"
    ))

And here's how to map it to a CheckBoxFor by using a non-nullable proxy property as a workaround:

In the ViewModel:

public bool NullableBooleanPropertyProxy
{
    get
    {
        return NullableBooleanProperty == true;
    }
    set
    {
        NullableBooleanProperty = value;
    }
}

In the View:

@model SomeModel

<!-- ...some HTML... -->

@Html.CheckBoxFor(m => m.NullableBooleanPropertyProxy)

The only downside of this workaround is that the null value will be treated as false: if you can't accept that, it's better to use a control that can support three states, such as the aforementioned DropDownListFor . 

For further info, read this post on my blog.

Adair answered 9/11, 2017 at 22:15 Comment(0)
D
0

To add to vapcguy answer, another more "cleaner" way to do it is like follows

@Html.CheckBox("IsDefault", Model?.IsDefault)

Or

<%= Html.CheckBox("IsDefault", Model?.IsDefault) %>
Delatorre answered 1/3, 2017 at 8:19 Comment(0)
P
0

You can create an editor template to render a checkbox for nullable Booleans. Name the template Boolean.cshtml to use it as the default for all of the Boolean properties within the site. Ensure that the file is in the folder ~/Views/Shared/EditorTemplates

@model bool?
@Html.CheckBox(String.Empty, Model??false)
Peugia answered 16/8, 2017 at 13:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.