asp.net mvc : Html.CheckBox가 추가 숨겨진 입력을 생성하는 이유


215

방금 Html.CheckBox("foo")하나 대신 2 개의 입력 을 생성 하는 것으로 나타났습니다 .

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


1
가능한 중복 질문에 대한 ericvg의 답변 은 확인란과 숨겨진 필드가 모두 제출 될 때 모델 바인더가 수행하는 작업을 설명합니다.
Theophilus

1
나는 이것이 내 jquery와 함께 쌓이고있는 것을 싫어한다.
Jerry Liang

2
mvc에 의한 이상한 구현. 두 값을 모두 보내는 것은 전혀 의미가 없습니다. Request.From [ "myCheckBox"]를 확인했는데 그 값은 true, false입니다. WTF. 뷰에서 컨트롤을 수동으로 작성해야했습니다.
Nick Masao

이것은 정말 체크 박스 Html.CheckBox (...) 그냥 입력 HTML을 사용하지 않는 다음 바람직하지 않은 경우
wnbates

답변:


198

확인란을 선택하지 않으면 양식 필드가 제출되지 않습니다. 숨겨진 필드에 항상 잘못된 값이있는 이유입니다. 확인란을 선택하지 않으면 양식에 여전히 숨겨진 필드의 값이 있습니다. 이것이 ASP.NET MVC가 확인란 값을 처리하는 방법입니다.

확인하려면 Html.Hidden이 아닌을 사용하여 확인란을 선택하십시오 <input type="checkbox" name="MyTestCheckboxValue"></input>. 확인란을 선택하지 않은 상태로두고 양식을 제출하고 서버 측에서 게시 된 요청 값을 확인하십시오. 확인란 값이 없다는 것을 알 수 있습니다. 숨겨진 필드가 있으면 값 이있는 MyTestCheckboxValue항목 이 포함 false됩니다.


52
확인란을 선택하지 않은 경우 분명히 답이 거짓이므로 항목을 다시 보낼 필요가 없습니다. 내 생각에는 바보 같은 디자인.
머핀 남자

54
@ TheMuffinMan : 이것은 바보 같은 옵션이 아닙니다. 뷰 모델 에 생성자에서 IsActive시작되는 속성이 있다고 가정 해 보겠습니다 true. 사용자는 확인란을 선택 해제하지만 값이 서버로 전송되지 않으므로 모델 바인더가 선택하지 않고 속성 값이 변경되지 않습니다. 모델 바인더는 값을 보내지 않으면이 값을 보내지 않기로 결정할 수 있기 때문에 false로 설정되었다고 가정해서는 안됩니다.
LukLed

21
그것은 무해한 확인란으로 시작한 다음보기 상태를 알기 전에 ASP.NET MVCForms로 진화합니다.
머핀 맨

4
@LukLed 댓글에 늦게 답장합니다 ...보기 모델에 속성 유형이 int이고 양식에 입력이 없으면 변경하는 값이 없기 때문에 기본값은 0이므로 논리에 결함이 있다고 생각합니다. 다른 속성과 마찬가지로 문자열의 기본값은 null입니다. 값을 보내지 않으면 null입니다. 생성자에서 속성을 true로 설정하는 예에서, 이는 솔직히 잘못된 디자인 결정이며 이제 http 랜드에서 확인란이 작동하는 방식으로 인해 밝혀졌습니다.
머핀 맨

8
이 섀도 잉 로직은 비활성화 된 확인란을 선택하지 않습니다. 체크되어 false있어도 값 을 보내 므로 혼동됩니다. ASP.NET이 기본 HTTP 동작과 호환되도록하려면 사용하지 않는 확인란이 값을 보내지 않아야합니다.
JustAMartin

31

숨겨진 입력을 추가하지 않도록 도우미를 작성할 수 있습니다.

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

4
이 경우에 대비하여 잠시 동안 트립되었습니다. 도우미가 네임 스페이스에있는 경우 @using Your.Name.Space.cshtml 면도기보기 파일 맨 위에 추가하는 것을 잊지 마십시오 .
ooXei1sh

3
@ ooXei1sh 또는 System.Web.Mvc.Html모든 뷰에서 액세스 할 수 있도록 네임 스페이스 에 도우미를 배치하십시오
Luke

1
양식 포스트 백 또는 양식 값으로 ajax를 통해 게시하려면 이것을 사용하려면 확인란의 onchange 이벤트를 통해 값을 true 또는 false로 설정해야합니다. @ Html.CheckBoxSimple (x => Model.Foo, 새로운 {value = Model.Foo, onchange = "toggleCheck (this)"}). 그런 다음 자바 스크립트 함수에서 ToggleCompleted (el) {var checked = $ (el) .is ( ': checked'); $ ( '# Foo'). val (확인); }
John81

12

확인란이 선택되어 제출되면

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

보내다


8

수동 접근 방식은 다음과 같습니다.

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

1
그리고 이것은 숨겨진 유형 값이 아닌 확인란 유형 값을 보장합니까?
브라이언 스위니

1
그것은 관련이 없습니다. 확인란이 선택되어 있지 않으면 게시되지 않습니다. 따라서 hiddenbox는 'false'를 갖습니다. 확인란을 선택하면 'true, true'값이 반환됩니다 (생각합니다). 'false'와 같지 않습니다.
Valamas 2016 년

16
아니요, 확인란을 선택하면 확인란과 숨겨진 필드가 모두 올바른 컨트롤로 전송되므로 true와 false가 모두 게시됩니다. 그런 다음 Mvc 바인더는 주어진 이름에 대해 실제 값이 존재하는지 확인하고 그렇다면 해당 값을 선호합니다. 게시 된 데이터를보고이를 확인할 수 있습니다. 단일 이름에 대해 true 및 false 값을 모두 갖습니다.
ZafarYousafi

이것은 내가 확인 한 번 저를 얻었다 값 == true의 경우
테리 Kernan

8

다음은 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);
    }
}

4

포함을 사용하면 "false"또는 "true, false"의 두 가지 가능한 게시 값으로 작동합니다.

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

1

숨겨진 입력은 스타일 체크 박스에 문제를 일으켰습니다. 그래서 Html Helper Extension을 만들어 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">

0

이것은 버그가 아닙니다! 양식을 서버에 게시 한 후 항상 값을 가질 가능성을 추가합니다. jQuery로 선택란 입력 필드를 처리하려면 prop 메소드를 사용하십시오 ( 'checked'특성을 매개 변수로 전달하십시오). 예:$('#id').prop('checked')


0

다음과 같이 모델의 생성자를 초기화하려고 할 수 있습니다.

public MemberFormModel() {
    foo = true;
}

그리고 당신의 관점에서 :

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

0

WebGrid가있을 때 이것이 실제로 문제를 일으킨다는 것을 알았습니다. WebGrid의 정렬 링크는 두 배로 증가한 querystring 또는 x = true & 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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.