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?!
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With