Getting Checkbox Value in ASP.NET MVC 4

C#asp.net Mvc-4

C# Problem Overview


I'm working on an ASP.NET MVC 4 app. This app has a basic form. The model for my form looks like the following:

public class MyModel
{
    public string Name { get; set; }
    public bool Remember { get; set; }
}

In my form, I have the following HTML.

<input id="Name" name="Name" type="text" value="@Model.Name" />
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
<label for="Remember">&nbsp;Remember Me?</label>

When I post the form, the Remember value in the model is always false. However, the Name property in the model has a value. I've tested this by setting a breakpoint in the following:

[HttpPost]
public ActionResult MyAction(MyModel model)
{
  Console.WriteLine(model.Remember.ToString());
}

I can't figure it out. Why isn't the Checkbox value getting set?

C# Solutions


Solution 1 - C#

@Html.EditorFor(x => x.Remember)

Will generate:

<input id="Remember" type="checkbox" value="true" name="Remember" />
<input type="hidden" value="false" name="Remember" />

How does it work:

  • If checkbox remains unchecked, the form submits only the hidden value (false)
  • If checked, then the form submits two fields (false and true) and MVC sets true for the model's bool property

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

This will always send the default value, if checked.

Solution 2 - C#

Since you are using Model.Name to set the value. I assume you are passing an empty view model to the View.

So the value for Remember is false, and sets the value on the checkbox element to false. This means that when you then select the checkbox, you are posting the value "false" with the form. When you don't select it, it doesn't get posted, so the model defaults to false. Which is why you are seeing a false value in both cases.

The value is only passed when you check the select box. To do a checkbox in Mvc use

@Html.CheckBoxFor(x => x.Remember)

or if you don't want to bind the model to the view.

@Html.CheckBox("Remember")

Mvc does some magic with a hidden field to persist values when they are not selected.

Edit, if you really have an aversion to doing that and want to generate the element yourself, you could do.

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />

Solution 3 - C#

Use only this

$("input[type=checkbox]").change(function () {
    if ($(this).prop("checked")) {
        $(this).val(true);
    } else {
        $(this).val(false);
    }
});

Solution 4 - C#

Instead of

 <input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

use:

 @Html.EditorFor(x => x.Remember)

That will give you a checkbox specifically for Remember

Solution 5 - C#

Okay, the checkbox is a little bit weird. When you use Html helper, it generates two checkbox inputs on the markup, and both of them get passed in as a name-value pair of IEnumerable if it is checked.

If it is not checked on the markup, it gets passed in only the hidden input which has value of false.

So for example on the markup you have:

      @Html.CheckBox("Chbxs") 

And in the controller action (make sure the name matches the checkbox param name on the controller):

      public ActionResult Index(string param1, string param2,
      string param3, IEnumerable<bool> Chbxs)

Then in the controller you can do some stuff like:

      if (Chbxs != null && Chbxs.Count() == 2)
        {
            checkBoxOnMarkup = true;
        }
        else
        {
            checkBoxOnMarkup = false;
        }

I know this is not an elegant solution. Hope someone here can give some pointers.

Solution 6 - C#

To convert a value returned from a check box in a form to a Boolean property I used the ValueProviderResult's in build converter in a custom ModelBinder.

ValueProviderResult cbValue = bindingContext.ValueProvider.GetValue("CheckBoxName");
bool value = (bool)cbValue.ConvertTo(typeof(bool));

Solution 7 - C#

If you really want to use plain HTML (for whatever reason) and not the built-in HtmlHelper extensions, you can do it this way.

Instead of

<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />

try using

<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked" : "") />

Checkbox inputs in HTML work so that when they're checked, they send the value, and when they're not checked, they don't send anything at all (which will cause ASP.NET MVC to fallback to the default value of the field, false). Also, the value of the checkbox in HTML can be anything not just true/false, so if you really wanted, you can even use a checkbox for a string field in your model.

If you use the built-in Html.RenderCheckbox, it actually outputs two inputs: checkbox and a hidden field so that a false value is sent when the checkbox is unchecked (not just nothing). That may cause some unexpected situations, like this:

Solution 8 - C#

If working with FormCollection rather than model, the assignment can be as simple as:

MyModel.Remember = fields["Remember"] != "false";

Solution 9 - C#

I ran into a similar issue and was able to get the checkbox value back by using a checkbox, hiddenfor and little JQuery like so:

@Html.CheckBox("isPreferred", Model.IsPreferred)
@Html.HiddenFor(m => m.IsPreferred)

<script>
                
    $("#isPreferred").change(function () {
                    
        $("#IsPreferred").val($("#isPreferred").val());
                    
    })
                
</script>

Solution 10 - C#

This has been a major pain and feels like it should be simpler. Here's my setup and solution.

I'm using the following HTML helper:

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

Then, in the controller, I am checking the form collection and processing accordingly:

bool activeFlag = collection["ActiveFlag"] == "false" ? false : true;
[modelObject].ActiveFlag = activeFlag;

Solution 11 - C#

I just ran into this (I can't believe it doesn't bind on/off!)

Anyways!

<input type="checkbox" name="checked" />

Will Post a value of "on" or "off".

This WONT bind to a boolean, but you can do this silly workaround!

 public class MyViewModel
 {
     /// <summary>
     /// This is a really dumb hack, because the form post sends "on" / "off"
     /// </summary>                    
     public enum Checkbox
     {
        on = 1,
        off = 0
     }
     public string Name { get; set; }
     public Checkbox Checked { get; set; }
}

Solution 12 - C#

@Html.EditorFor(x => x.ShowComment)


$(function () {
        // set default value to control on document ready instead of 'on'/'off' 
        $("input[type='checkbox'][name='ShowComment']").val(@Model.ShowComment.ToString().ToLower());
    });

    $("#ShowComment").change(function() {
        // this block sets value to checkbox control for "true" / "false"

        var chkVal = $("input[type='checkbox'][name='ShowComment']").val();
        if (chkVal == 'false') $("input[type='checkbox'][name='ShowComment']").val(true);
        else $("input[type='checkbox'][name='ShowComment']").val(false);

    });

Solution 13 - C#

For the MVC using Model. Model:

public class UserInfo
{
    public string UserID { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public bool RememberMe { get; set; }
}

HTML:

<input type="checkbox" value="true" id="checkbox1" name="RememberMe" checked="@Model.RememberMe"/>
<label for="checkbox1"></label>

In [HttpPost] function, we can get its properties.

[HttpPost]
public ActionResult Login(UserInfo user)
{
   //...
   return View(user);
}

Solution 14 - C#

For multiple checkbox with same name... Code to remove unnecessary false :

List<string> d_taxe1 = new List<string>(Request.Form.GetValues("taxe1"));
d_taxe1 = form_checkbox.RemoveExtraFalseFromCheckbox(d_taxe1);

Function

public class form_checkbox
{

    public static List<string> RemoveExtraFalseFromCheckbox(List<string> val)
    {
        List<string> d_taxe1_list = new List<string>(val);

        int y = 0;

        foreach (string cbox in val)
        {

            if (val[y] == "false")
            {
                if (y > 0)
                {
                    if (val[y - 1] == "true")
                    {
                        d_taxe1_list[y] = "remove";
                    }
                }

            }

            y++;
        }

        val = new List<string>(d_taxe1_list);

        foreach (var del in d_taxe1_list)
            if (del == "remove") val.Remove(del);

        return val;
    
    }      



}

Use it :

int x = 0;
foreach (var detail in d_prix){
factured.taxe1 = (d_taxe1[x] == "true") ? true : false;
x++;
}

Solution 15 - C#

public ActionResult Index(string username, string password, string rememberMe)
{
   if (!string.IsNullOrEmpty(username))
   {
      bool remember = bool.Parse(rememberMe);
      //...
   }
   return View();
}

Solution 16 - C#

Modify Remember like this

public class MyModel
{
    public string Name { get; set; }
    public bool? Remember { get; set; }
}

Use nullable bool in controller and fallback to false on null like this

[HttpPost]
public ActionResult MyAction(MyModel model)
{
    model.Remember = model.Remember ?? false;
    Console.WriteLine(model.Remember.ToString());
}

Solution 17 - C#

In my case I was not setting the model property "Remember" in the get method. Check your logic in the controller. You may be doing the same. I hope this help!

Solution 18 - C#

I read through the other answers and wasn't quite getting it to work - so here's the solution I ended up with.

My form uses the Html.EditorFor(e => e.Property) to generate the checkbox, and using FormCollection in the controller, this passes a string value of 'true,false' in the controller.

When I'm handling the results I use a loop to cycle through them - I also use an InfoProperty instance to represent the current model value being assessed from the form.

So instead I just check if the string returned starts with the word 'true' and then set a boolean variable to true and pass that into the return model.

if (KeyName.EndsWith("OnOff"))
{
    // set on/off flags value to the model instance
    bool keyTrueFalse = false;
    if(values[KeyName].StartsWith("true"))
    {
        keyTrueFalse = true;
    }
    infoProperty.SetValue(processedInfo, keyTrueFalse);
}

Solution 19 - C#

Crazy idea... Asp.Net MVC should just accept checked checkboxes as "true" when passed to bools in models... .

I think the below - where a ModelBinder accepts the HTML standard "on" to mean true - should've always been the default implementation in Asp.Net MVC. This solution is for the Classic/Non-Core, but, it should be easy to adapt to Core.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace Brass9.Web.Mvc.ModelBinders
{
	public class FixedCheckboxFormModelBinder : System.Web.Mvc.IModelBinder
	{
		public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
		{
			if (
				// Form POST
				!controllerContext.HttpContext.Request.ContentType.StartsWith
					("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)
				/*
				// Note: This is implied - by the way we add this ModelBinder to the global app list (typeof(bool))
				||
				bindingContext.ModelMetadata.ModelType != typeof(bool)
				*/
			)
			{
				return null;
			}

			string name = bindingContext.ModelName;
			var valueProviderResult = bindingContext.ValueProvider.GetValue(name);

			if (valueProviderResult.AttemptedValue == "on")
			{
				var replacementResult = new ValueProviderResult(true, "on", System.Globalization.CultureInfo.CurrentCulture);
				bindingContext.ModelState.SetModelValue(name, replacementResult);
				return true;
			}

			return null;
		}
	}
}

Then enable it in Global.asax.cs, in Application_Start():

ModelBinders.Binders.Add(typeof(bool), new Brass9.Web.Mvc.ModelBinders.FixedCheckboxFormModelBinder());

So, we just build a custom ModelBinder, filter just for Model values expecting a bool coming in over form POST, and passing us the HTML standard "on" - safely limiting its intervention to checkboxes.

It's actually sort of strange trying to apply this fix, because most documentation about ModelBinders is praise with very little in the way of clear how-tos.

Why we solved it this way:

We're migrating an older app to entirely use original Asp.Net MVC (non-Core). Not only would moving all the checkboxes over to @Html.Checkbox... (much wasn't written this way) take a very long time, it also produces a lot of undesirable results, because of the extra, unnecessary hidden input, and the difficulty of migrating pages over. For example, we know there are some pages that have Javascript walking the DOM expecting elements in a specific order, that the hidden input would break, and don't want to comb through every single page looking for these bugs.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJQuery MobileView Question on Stackoverflow
Solution 1 - C#webdeveloperView Answer on Stackoverflow
Solution 2 - C#Dan SaltmerView Answer on Stackoverflow
Solution 3 - C#Bekir TopuzView Answer on Stackoverflow
Solution 4 - C#RobertView Answer on Stackoverflow
Solution 5 - C#YiniView Answer on Stackoverflow
Solution 6 - C#ChrisView Answer on Stackoverflow
Solution 7 - C#Tom PažourekView Answer on Stackoverflow
Solution 8 - C#Aaron CarterView Answer on Stackoverflow
Solution 9 - C#John MeyerView Answer on Stackoverflow
Solution 10 - C#fujiifaceView Answer on Stackoverflow
Solution 11 - C#YablargoView Answer on Stackoverflow
Solution 12 - C#SurendranView Answer on Stackoverflow
Solution 13 - C#LulalaView Answer on Stackoverflow
Solution 14 - C#Pascal CarmoniView Answer on Stackoverflow
Solution 15 - C#user586399View Answer on Stackoverflow
Solution 16 - C#irfandarView Answer on Stackoverflow
Solution 17 - C#Nour LababidiView Answer on Stackoverflow
Solution 18 - C#C GilView Answer on Stackoverflow
Solution 19 - C#Chris MoschiniView Answer on Stackoverflow