asp.net mvc:为什么Html.CheckBox会生成额外的隐藏输入

时间:2010-04-23 08:53:03

标签: asp.net-mvc

我刚注意到Html.CheckBox("foo")生成2个输入而不是1个,有人知道为什么会这样吗?

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

12 个答案:

答案 0 :(得分:181)

如果未选中复选框,则不提交表单字段。这就是隐藏领域总是存在虚假价值的原因。如果未选中复选框,则表单仍将具有隐藏字段的值。这就是ASP.NET MVC处理复选框值的方式。

如果您想确认这一点,请在表单上放置一个复选框,而不是使用Html.Hidden,但使用<input type="checkbox" name="MyTestCheckboxValue"></input>。保持复选框未选中,提交表单并查看服务器端的已发布请求值。你会看到没有复选框值。如果您有隐藏字段,则会包含MyTestCheckboxValue条目,其值为false

答案 1 :(得分:30)

您可以编写帮助以防止添加隐藏的输入:

using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class HelperUI
{
    public static MvcHtmlString CheckBoxSimple(this HtmlHelper htmlHelper, string name, object htmlAttributes)
    {
        string checkBoxWithHidden = htmlHelper.CheckBox(name, htmlAttributes).ToHtmlString().Trim();
        string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
        return new MvcHtmlString(pureCheckBox);
    }
}

使用它:

@Html.CheckBoxSimple("foo", new {value = bar.Id})

答案 2 :(得分:11)

选中复选框并提交后执行此

if ($('[name="foo"]:checked').length > 0)
    $('[name="foo"]:hidden').val(true);

Refer

答案 3 :(得分:7)

手动方法是:

bool IsDefault = (Request.Form["IsDefault"] != "false");

答案 4 :(得分:5)

这是Alexander Trofimov解决方案的强类型版本:

using System.Web.Mvc;
using System.Web.Mvc.Html;

public static class HelperUI
{
    public static MvcHtmlString CheckBoxSimpleFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, bool>> expression, object htmlAttributes)
    {
        string checkBoxWithHidden = htmlHelper.CheckBoxFor(expression, htmlAttributes).ToHtmlString().Trim();
        string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
        return new MvcHtmlString(pureCheckBox);
    }
}

答案 5 :(得分:2)

从 ASP.NET (Core) 5 开始,将此添加到您的启动:

services.Configure<MvcViewOptions>(options =>
{
    // Disable hidden checkboxes
    options.HtmlHelperOptions.CheckBoxHiddenInputRenderMode = CheckBoxHiddenInputRenderMode.None;
});

以您的观点为例:

<input class="form-check-input" asp-for="@Model.YourBool" />

不再在您的表单中创建此属性的附加隐藏字段:

<input class="form-check-input" type="checkbox" data-val="true" data-val-required="The YourBool field is required." id="YourBool" name="YourBool" value="true" />

来源: https://github.com/dotnet/aspnetcore/pull/13014#issuecomment-674449674

答案 6 :(得分:1)

使用包含,它将使用两个可能的帖子值:“false”或“true,false”。

bool isChecked = Request.Form["foo"].Contains("true");

答案 7 :(得分:1)

截至2020/11和.NET 5处于预览阶段,有一个pull request应该可以控制此行为。谢谢你们!

无论如何,如果有人发现它有用,亚历山大·特罗菲莫夫的答案的.NET Core 3.0端口:

public static IHtmlContent CheckBoxSimple(this IHtmlHelper htmlHelper, string name)
{
    TextWriter writer = new StringWriter();

    IHtmlContent html = htmlHelper.CheckBox(name);
    html.WriteTo(writer, HtmlEncoder.Default);

    string checkBoxWithHidden = writer.ToString();

    string pureCheckBox = checkBoxWithHidden.Substring(0, checkBoxWithHidden.IndexOf("<input", 1));
    return new HtmlString(pureCheckBox);
}

答案 8 :(得分:0)

这不是错误!在将表单发布到服务器之后,它增加了始终具有值的可能性。 如果要使用jQuery处理复选框输入字段,请使用prop方法(将'checked'属性作为参数传递)。 示例:$('#id').prop('checked')

答案 9 :(得分:0)

您可以尝试初始化模型的构造函数:

public MemberFormModel() {
    foo = true;
}

并在您看来:

@html.Checkbox(...)
@html.Hidden(...)

答案 10 :(得分:0)

隐藏的输入导致样式复选框出现问题。因此,我创建了一个HTML帮助程序扩展,以将隐藏的输入放置在包含CheckBox的div之外。

using System;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;
using System.Web.Routing;

namespace YourNameSpace
{
    public static class HtmlHelperExtensions
    {
        public static MvcHtmlString CustomCheckBoxFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string labelText)
        {
            //get the data from the model binding
            var fieldName = ExpressionHelper.GetExpressionText(expression);
            var fullBindingName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(fieldName);
            var fieldId = TagBuilder.CreateSanitizedId(fullBindingName);
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            var modelValue = metaData.Model;

            //create the checkbox
            TagBuilder checkbox = new TagBuilder("input");
            checkbox.MergeAttribute("type", "checkbox");
            checkbox.MergeAttribute("value", "true"); //the visible checkbox must always have true
            checkbox.MergeAttribute("name", fullBindingName);
            checkbox.MergeAttribute("id", fieldId);

            //is the checkbox checked
            bool isChecked = false;
            if (modelValue != null)
            {
                bool.TryParse(modelValue.ToString(), out isChecked);
            }
            if (isChecked)
            {
                checkbox.MergeAttribute("checked", "checked");
            }

            //add the validation
            checkbox.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(fieldId, metaData));

            //create the outer div
            var outerDiv = new TagBuilder("div");
            outerDiv.AddCssClass("checkbox-container");

            //create the label in the outer div
            var label = new TagBuilder("label");
            label.MergeAttribute("for", fieldId);
            label.AddCssClass("checkbox");

            //render the control
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(outerDiv.ToString(TagRenderMode.StartTag));
            sb.AppendLine(checkbox.ToString(TagRenderMode.SelfClosing));
            sb.AppendLine(label.ToString(TagRenderMode.StartTag));
            sb.AppendLine(labelText); //the label
            sb.AppendLine("<svg width=\"10\" height=\"10\" class=\"icon-check\"><use xlink:href=\"/icons.svg#check\"></use></svg>"); //optional icon
            sb.AppendLine(label.ToString(TagRenderMode.EndTag));
            sb.AppendLine(outerDiv.ToString(TagRenderMode.EndTag));

            //create the extra hidden input needed by MVC outside the div
            TagBuilder hiddenCheckbox = new TagBuilder("input");
            hiddenCheckbox.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
            hiddenCheckbox.MergeAttribute("name", fullBindingName);
            hiddenCheckbox.MergeAttribute("value", "false");
            sb.Append(hiddenCheckbox.ToString(TagRenderMode.SelfClosing));

            //return the custom checkbox
            return MvcHtmlString.Create(sb.ToString());
        }

结果

<div class="checkbox-container">
    <input checked="checked" id="Model_myCheckBox" name="Model.myCheckBox" type="checkbox" value="true">
    <label class="checkbox" for="Model_myCheckBox">
        The checkbox label
        <svg width="10" height="10" class="icon-check"><use xlink:href="/icons.svg#check"></use></svg>
    </label>
</div>
<input name="Model.myCheckBox" type="hidden" value="false">

答案 11 :(得分:-1)

当我有一个WebGrid时,我发现这确实引起了问题。 WebGrid上的排序链接将通过加倍的查询字符串或x = true&amp; x = false转换为x = true,false并在复选框中导致解析错误。

我最终使用jQuery删除客户端的隐藏字段:

    <script type="text/javascript">
    $(function () {
        // delete extra hidden fields created by checkboxes as the grid links mess this up by doubling the querystring parameters
        $("input[type='hidden'][name='x']").remove();
    });
    </script>