[英]Getting Checkbox Value in ASP.NET MVC 4
我正在开发 ASP.NET MVC 4 应用程序。 这个应用程序有一个基本的形式。 我的表单的 model 如下所示:
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"> Remember Me?</label>
当我发布表单时,model 中的 Remember 值始终为 false。 但是,model 中的 Name 属性有一个值。 我通过在下面设置断点来测试它:
[HttpPost]
public ActionResult MyAction(MyModel model)
{
Console.WriteLine(model.Remember.ToString());
}
我想不通。 为什么未设置 Checkbox 值?
@Html.EditorFor(x => x.Remember)
会产生:
<input id="Remember" type="checkbox" value="true" name="Remember" />
<input type="hidden" value="false" name="Remember" />
它是如何工作的:
checkbox
,则表单仅提交hidden
值(false) bool
属性设置true
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
如果选中,它将始终发送默认值。
由于您使用Model.Name来设置值。 我假设您将空视图模型传递给View。
因此,Remember的值为false,并将checkbox元素的值设置为false。 这意味着当您选择复选框时,您将使用表单发布值“false”。 如果不选择它,则不会发布,因此模型默认为false。 这就是为什么你在两种情况下都看到了错误的价值。
只有在选中复选框时才会传递该值。 在Mvc中使用复选框
@Html.CheckBoxFor(x => x.Remember)
或者如果您不想将模型绑定到视图。
@Html.CheckBox("Remember")
当没有选择时,Mvc会使用隐藏字段来保持值。
编辑,如果你真的厌恶这样做,并希望自己生成元素,你可以做到。
<input id="Remember" name="Remember" type="checkbox" value="true" @(Model.Remember ? "checked=\"checked\"" : "") />
仅使用此功能
$("input[type=checkbox]").change(function () {
if ($(this).prop("checked")) {
$(this).val(true);
} else {
$(this).val(false);
}
});
好的,复选框有点奇怪。 当您使用Html帮助程序时,它会在标记上生成两个复选框输入,如果选中它们,它们都将作为IEnumerable的名称 - 值对传入。
如果未在标记上检查,则仅传入值为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;
}
我知道这不是一个优雅的解决方案。 希望有人在这里可以提供一些指示。
代替
<input id="Remember" name="Remember" type="checkbox" value="@Model.Remember" />
使用:
@Html.EditorFor(x => x.Remember)
这将为您提供专门用于记住的复选框
要将从表单中的复选框返回的值转换为布尔属性,我在自定义ModelBinder中使用构建转换器中的ValueProviderResult。
ValueProviderResult cbValue = bindingContext.ValueProvider.GetValue("CheckBoxName");
bool value = (bool)cbValue.ConvertTo(typeof(bool));
我遇到了类似的问题,并且能够通过使用复选框,hiddenfor和小JQuery来获取复选框值,如下所示:
@Html.CheckBox("isPreferred", Model.IsPreferred)
@Html.HiddenFor(m => m.IsPreferred)
<script>
$("#isPreferred").change(function () {
$("#IsPreferred").val($("#isPreferred").val());
})
</script>
这是一个很大的痛苦,感觉应该更简单。 这是我的设置和解决方案。
我正在使用以下HTML帮助器:
@Html.CheckBoxFor(model => model.ActiveFlag)
然后,在控制器中,我正在检查表单集合并进行相应处理:
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);
});
对于使用Model的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);
}
我刚碰到这个(我不敢相信它不会打开/关闭!)
无论如何!
<input type="checkbox" name="checked" />
将发布“开”或“关”的值。
这个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; }
}
对于具有相同名称的多个复选框...删除不必要的错误代码:
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();
}
修改记住这样
public class MyModel
{
public string Name { get; set; }
public bool? Remember { get; set; }
}
在控制器中使用可空的bool,并像这样在null上回退为false
[HttpPost]
public ActionResult MyAction(MyModel model)
{
model.Remember = model.Remember ?? false;
Console.WriteLine(model.Remember.ToString());
}
在我的情况下,我没有在get方法中设置模型属性“Remember”。 检查控制器中的逻辑。 你可能也在这样做。 我希望这有帮助!
如果你真的想使用纯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回退到默认值field, false
)。 此外,HTML中复选框的值可以是任何不仅是真/假的值,因此如果您真的想要,您甚至可以使用模型中字符串字段的复选框。
如果您使用内置的Html.RenderCheckbox
,它实际上输出两个输入:复选框和隐藏字段,以便在取消选中复选框时发送错误值(不只是没有)。 这可能会导致一些意外情况,例如:
我仔细阅读了其他答案,并没有完全开始工作 - 所以这就是我最终解决的问题。
我的表单使用Html.EditorFor(e => e.Property)
生成复选框,并在控制器中使用FormCollection
,它在控制器中传递字符串值'true,false'
。
当我处理结果时,我使用循环来循环它们 - 我还使用InfoProperty
实例来表示从表单中评估的当前模型值。
所以我只是检查返回的字符串是否以单词'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);
}
疯狂的想法......当传递给模型中的布尔时,Asp.Net MVC 应该只接受选中的复选框为“true”......。
我认为以下 - ModelBinder 接受 HTML 标准“开”意味着 true - 应该始终是 Asp.Net MVC 中的默认实现。 此解决方案适用于 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;
}
}
}
然后在 Global.asax.cs 的Application_Start()
中启用它:
ModelBinders.Binders.Add(typeof(bool), new Brass9.Web.Mvc.ModelBinders.FixedCheckboxFormModelBinder());
因此,我们只是构建了一个自定义 ModelBinder,仅针对 Model 值进行过滤,期望通过 POST 形式传入布尔值,并向我们传递 HTML 标准“开启”——安全地将其干预限制在复选框中。
尝试应用此修复程序实际上有点奇怪,因为大多数关于 ModelBinders 的文档都受到赞扬,但很少有清晰的操作方法。
为什么我们这样解决:
我们正在迁移一个旧的应用程序以完全使用原始的 Asp.Net MVC(非核心)。 不仅将所有复选框移动到@Html.Checkbox...
(很多不是这样写的)需要很长时间,它还会产生很多不良结果,因为额外的、不必要的隐藏输入,以及迁移页面的难度。 例如,我们知道有些页面有 Javascript 以特定顺序遍历 DOM 期望元素,隐藏的输入会中断,并且不想梳理每个页面来寻找这些错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.