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

我正在开发一个 ASP.NET MVC 4应用程序。这个应用程序有一个基本的形式。我的表单的模型如下:

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

在我的表单中,我有以下 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>

当我发布表单时,模型中的 Remembervalue 始终为 false。但是,模型中的 Name 属性具有一个值。我通过在下面设置一个断点来测试它:

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

我想不出来,为什么没有设置 Checkbox 值?

333936 次浏览

而不是

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

用途:

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

这将为“记住”专门提供一个复选框

因为您使用的是 Model。名称来设置值。我假设您正在向 View 传递一个空视图模型。

因此,Remember 的值为 false,并将复选框元素上的值设置为 false。这意味着当您然后选择复选框时,您将在表单中提交值“ false”。如果您没有选择它,它就不会被发布,因此模型默认为 false。这就是为什么你在两种情况下都看到了错误的价值。

只有当您选中选择框时,该值才会被传递

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

或者不想将模型绑定到视图。

@Html.CheckBox("Remember")

Mvc 使用一个隐藏字段来保存未选中的值。

编辑,如果您真的不喜欢这样做,并且希望自己生成元素,那么您可以这样做。

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

将产生:

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

它是如何工作的:

  • 如果 checkbox仍未选中,则表单只提交 hidden值(false)
  • 如果选中,则表单提交两个字段(false 和 true)和 MVC 集 true表示模型的 bool属性

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

如果选中,这将始终发送默认值。

好吧,这个复选框有点奇怪。 当您使用 Html helper 时,它会在标记上生成两个复选框输入,如果选中它,它们都会作为 IEnumable 的名称-值对传入。

如果未在标记上检查它,则只传递值为 false 的隐藏输入。

例如,在标记上:

      @Html.CheckBox("Chbxs")

在控制器操作中(确保名称与控制器上的复选框参数名称匹配) :

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

然后在控制器中你可以做一些事情,比如:

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

我知道这不是一个优雅的解决方案。希望这里有人能给点建议。

要将窗体中复选框返回的值转换为 Boolean 属性,我在自定义 ModelBinder 中使用了 ValueProviderResult 的生成转换器。

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

我遇到了一个类似的问题,通过使用一个复选框、 iddenfor 和小 JQuery,我可以得到复选框的值,如下所示:

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


<script>


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


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


})


</script>

我刚好碰到了这个(我不敢相信它居然不绑定 on/off!)

不管怎样!

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

将发布一个值“ on”或“ off”。

这个 不会绑定到一个布尔值,但是你可以做这个愚蠢的变通!

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


});

对于同名的多个复选框... 代码删除不必要的 false:

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

功能

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;


}






}

使用它:

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

这一直是一个主要的痛苦,感觉应该更简单。这里是我的设置和解决方案。

我使用以下 HTML 助手:

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

然后,在控制器中,我检查表单收集并相应地处理:

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

像这样修改“记住”

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

在控制器中使用 nullable bool,在 null 时回退为 false,如下所示

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

只用这个

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

在我的例子中,我没有在 get 方法中设置模型属性“ Remember”。检查控制器中的逻辑。你可能也在做同样的事情。我希望这有帮助!

为 MVC 使用模型。 型号:

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>

在[ HttpPost ]函数中,我们可以得到它的性质。

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

如果您真的想使用纯 HTML (不管什么原因)而不是内置的 HtmlHelper 扩展,您可以这样做。

而不是

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

尝试使用

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

HTML 中的复选框输入可以正常工作,所以当它们被选中时,它们会发送值,而当它们没有被选中时,它们根本不会发送任何东西(这将导致 ASP.NET MVC 回退到字段的默认值 false)。此外,HTML 中复选框的值可以是任何值,而不仅仅是 true/false,所以如果您真的想要,您甚至可以在模型中使用字符串字段的复选框。

如果使用内置的 Html.RenderCheckbox,它实际上输出两个输入: 复选框和一个隐藏字段,以便在未选中复选框时发送一个假值(而不是什么都没有)。这可能会导致一些意想不到的情况,比如:

我通读了其他的答案,并没有完全得到它的工作-所以这里的解决方案,我结束了。

我的表单使用 Html.EditorFor(e => e.Property)生成复选框,并在控制器中使用 FormCollection,这将在控制器中传递一个字符串值 'true,false'

当我处理结果时,我使用一个循环来遍历它们——我还使用一个 InfoProperty实例来表示从表单评估的当前模型值。

因此,我只是检查返回的字符串是否以单词 'true'开头,然后将一个布尔变量设置为 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);
}

如果使用 FormCollection 而不是 model,赋值可以简单如下:

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

疯狂的想法... Asp.Net MVC 在传递给模型中的布尔时应该只接受复选框为“ true”..。

我认为下面的代码—— ModelBinder 接受 HTML 标准“ on”表示真实——应该一直是 Asp 中的默认实现。网络 MVC。这个解决方案适用于经典/非核心,但是,它应该很容易适应核心。

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

然后在 Application_Start()中的 Global.asax.cs 中启用它:

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

因此,我们只需构建一个定制的 ModelBinder,过滤期望在 POST 表单上显示一个 bool 的 Model 值,并将 HTML 标准“ on”传递给我们——安全地将其干预限制在复选框中。

实际上,尝试应用这个修复程序有点奇怪,因为大多数关于 ModelBinders 的文档都是赞扬性的,只有很少的清晰的 how-to。

为什么我们这样解决:

我们正在迁移一个旧的应用程序,完全使用原来的 Asp。Net MVC (非核心)。将所有复选框移动到 @Html.Checkbox...不仅需要很长时间(很多不是这样写的) ,而且还会产生很多不想要的结果,因为额外的、不必要的隐藏输入,以及难以移动页面。例如,我们知道有些页面使用 Javascript 在 DOM 中按照特定的顺序遍历元素,隐藏的输入会中断,并且不想梳理每一个页面来寻找这些 bug。