Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 5 Checkbox returns “False,false” or “false”

At first glance this post may look like a duplicate, but it's not. Believe me, I've looked all over Stack Overflow to no avail.

Anyway, I'm getting some weird behaviour from Html.CheckBoxFor.

I have a view model with this following defined property

[Display(Name = "User is active")]
public bool IsActive { get; set; }

It's initialized before the view

if (userInfo.isActive != null)
{
    //Cast to bool because userInfo.isActive is Nullable<bool>
    model.IsActive = (bool)userInfo.isActive;
}

ModelState.Clear();

return View(model);

Then rendered in an Html.BeginForm as

<div class="form-group">
    @Html.LabelFor(model => model.IsActive, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.CheckBoxFor(model => model.IsActive, htmlAttributes: new { @value = Model.IsActive /*Also tried @checked = Model.IsActive*/ })
        @Html.ValidationMessageFor(model => model.IsActive)
    </div>
</div>

And returned to the controller

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditProfile(EditProfileViewModel model, string Roles, HttpPostedFileBase ProfileImage)
{
    //There's a lot more up here, but it's not relevant to the problem
    userInfo.isActive = model.IsActive;
    var tmp = Request.Form["IsActive"]; //Added just to check the form value

    try
    {
        db.Entry(userInfo).State = EntityState.Modified;
        //Assign changed data to userInfo
        db.SaveChanges();
    }
}

When model.IsActive is initialized as true and I don't uncheck the checkbox the value of model.IsActive in the controller post is true, or if I do uncheck the checkbox then the value of model.IsActive comes back as false and everything is hunky-dory.

The problem occurs when model.IsActive is initialized as false. I read a lot of Stack Overflow posts explaining that if the checkbox is unchecked then "false" is returned and if it is checked "true,false" is returned, but that's not the behaviour I'm getting. When the checkbox is initialized as false and I check it in the view the value of model.IsActive still comes back false and when I check the value of the form element (see "var tmp" in controller post) it's "false, false". "True,false" is the expected value, is it not? This only happens when trying to change the model value from false to true, no issues going from true to false.

So Stack Overflow, what the heck is happening?!

like image 378
Francis Avatar asked Oct 20 '22 03:10

Francis


1 Answers

You don't need to change the value property of the checkbox. If yu use the helper without it you will see that

@Html.CheckBoxFor(model => model.IsActive)

is rendered to

<input data-val="true" data-val-required="The IsActive field is required." id="IsActive" name="IsActive" type="checkbox" value="true" class="valid">

You can see that although the Model.IsActive is set to false the value property of an input is still true

By The way if you look at the source code for CheckBox helper you will see that value=true is hardcoded there (So you should not change it):

private static MvcHtmlString CheckBoxHelper(HtmlHelper htmlHelper, ModelMetadata metadata, string name, bool? isChecked, IDictionary<string, object> htmlAttributes)
        {
            RouteValueDictionary attributes = ToRouteValueDictionary(htmlAttributes);

            bool explicitValue = isChecked.HasValue;
            if (explicitValue)
            {
                attributes.Remove("checked"); // Explicit value must override dictionary
            }

            return InputHelper(htmlHelper,
                               InputType.CheckBox,
                               metadata,
                               name,
                               value: "true",
                               useViewData: !explicitValue,
                               isChecked: isChecked ?? false,
                               setId: true,
                               isExplicitValue: false,
                               format: null,
                               htmlAttributes: attributes);
        }
like image 61
Alex Art. Avatar answered Oct 27 '22 10:10

Alex Art.