简体   繁体   English

在 ASP.NET MVC 4 中获取复选框值

[英]Getting Checkbox Value in ASP.NET MVC 4

I'm working on an ASP.NET MVC 4 app.我正在开发 ASP.NET MVC 4 应用程序。 This app has a basic form.这个应用程序有一个基本的形式。 The model for my form looks like the following:我的表单的 model 如下所示:

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

In my form, I have the following HTML.在我的表格中,我有以下 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.当我发布表单时,model 中的 Remember 值始终为 false。 However, the Name property in the model has a value.但是,model 中的 Name 属性有一个值。 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?为什么未设置 Checkbox 值?

@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) 如果未选中checkbox ,则表单仅提交hidden值(false)
  • If checked, then the form submits two fields (false and true) and MVC sets true for the model's bool property 如果选中,则表单提交两个字段(false和true),MVC为模型的bool属性设置true

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

This will always send the default value, if checked. 如果选中,它将始终发送默认值。

Since you are using Model.Name to set the value. 由于您使用Model.Name来设置值。 I assume you are passing an empty view model to the View. 我假设您将空视图模型传递给View。

So the value for Remember is false, and sets the value on the checkbox element to false. 因此,Remember的值为false,并将checkbox元素的值设置为false。 This means that when you then select the checkbox, you are posting the value "false" with the form. 这意味着当您选择复选框时,您将使用表单发布值“false”。 When you don't select it, it doesn't get posted, so the model defaults to false. 如果不选择它,则不会发布,因此模型默认为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 在Mvc中使用复选框

@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. 当没有选择时,Mvc会使用隐藏字段来保持值。

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\"" : "") />

Use only this 仅使用此功能

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

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. 当您使用Html帮助程序时,它会在标记上生成两个复选框输入,如果选中它们,它们都将作为IEnumerable的名称 - 值对传入。

If it is not checked on the markup, it gets passed in only the hidden input which has value of false. 如果未在标记上检查,则仅传入值为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. 希望有人在这里可以提供一些指示。

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 这将为您提供专门用于记住的复选框

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. 要将从表单中的复选框返回的值转换为布尔属性,我在自定义ModelBinder中使用构建转换器中的ValueProviderResult。

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

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: 我遇到了类似的问题,并且能够通过使用复选框,hiddenfor和小JQuery来获取复选框值,如下所示:

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

<script>

    $("#isPreferred").change(function () {

        $("#IsPreferred").val($("#isPreferred").val());

    })

</script>

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帮助器:

@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;

如果使用FormCollection而不是模型,则赋值可以如下所示:

MyModel.Remember = fields["Remember"] != "false";
@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);

    });

For the MVC using Model. 对于使用Model的MVC。 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: 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]函数中,我们可以获得它的属性。

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

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! 这个WONT绑定到一个布尔值,但你可以做这个愚蠢的解决方法!

 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; }
}

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++;
}
public ActionResult Index(string username, string password, string rememberMe)
{
   if (!string.IsNullOrEmpty(username))
   {
      bool remember = bool.Parse(rememberMe);
      //...
   }
   return View();
}

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 在控制器中使用可空的bool,并像这样在null上回退为false

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

In my case I was not setting the model property "Remember" in the get method. 在我的情况下,我没有在get方法中设置模型属性“Remember”。 Check your logic in the controller. 检查控制器中的逻辑。 You may be doing the same. 你可能也在这样做。 I hope this help! 我希望这有帮助!

If you really want to use plain HTML (for whatever reason) and not the built-in HtmlHelper extensions, you can do it this way. 如果你真的想使用纯HTML(无论出于何种原因)而不是内置的HtmlHelper扩展,你可以这样做。

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 ). HTML中的复选框输入工作,以便在检查时,它们发送值,当它们未被检查时,它们根本不发送任何内容(这将导致ASP.NET MVC回退到默认值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. 此外,HTML中复选框的值可以是任何不仅是真/假的值,因此如果您真的想要,您甚至可以使用模型中字符串字段的复选框。

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). 如果您使用内置的Html.RenderCheckbox ,它实际上输出两个输入:复选框和隐藏字段,以便在取消选中复选框时发送错误值(不只是没有)。 That may cause some unexpected situations, like this: 这可能会导致一些意外情况,例如:

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. 我的表单使用Html.EditorFor(e => e.Property)生成复选框,并在控制器中使用FormCollection ,它在控制器中传递字符串值'true,false'

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. 当我处理结果时,我使用循环来循环它们 - 我还使用InfoProperty实例来表示从表单中评估的当前模型值。

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. 所以我只是检查返回的字符串是否以单词'true'开头,然后将boolean变量设置为true并将其传递给返回模型。

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);
}

Crazy idea... Asp.Net MVC should just accept checked checkboxes as "true" when passed to bools in models... .疯狂的想法......当传递给模型中的布尔时,Asp.Net MVC 应该只接受选中的复选框为“true”......。

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.我认为以下 - ModelBinder 接受 HTML 标准“开”意味着 true - 应该始终是 Asp.Net MVC 中的默认实现。 This solution is for the Classic/Non-Core, but, it should be easy to adapt to Core.此解决方案适用于 Classic/Non-Core,但应该很容易适应 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() :然后在 Global.asax.cs 的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.因此,我们只是构建了一个自定义 ModelBinder,仅针对 Model 值进行过滤,期望通过 POST 形式传入布尔值,并向我们传递 HTML 标准“开启”——安全地将其干预限制在复选框中。

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.尝试应用此修复程序实际上有点奇怪,因为大多数关于 ModelBinders 的文档都受到赞扬,但很少有清晰的操作方法。

Why we solved it this way:为什么我们这样解决:

We're migrating an older app to entirely use original Asp.Net MVC (non-Core).我们正在迁移一个旧的应用程序以完全使用原始的 Asp.Net MVC(非核心)。 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.不仅将所有复选框移动到@Html.Checkbox... (很多不是这样写的)需要很长时间,它还会产生很多不良结果,因为额外的、不必要的隐藏输入,以及迁移页面的难度。 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.例如,我们知道有些页面有 Javascript 以特定顺序遍历 DOM 期望元素,隐藏的输入会中断,并且不想梳理每个页面来寻找这些错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM