Programming

CheckBoxFor가 추가 입력 태그를 렌더링하는 이유는 무엇이며 FormCollection을 사용하여 값을 얻는 방법은 무엇입니까?

procodes 2020. 7. 3. 22:15
반응형

CheckBoxFor가 추가 입력 태그를 렌더링하는 이유는 무엇이며 FormCollection을 사용하여 값을 얻는 방법은 무엇입니까?


내 ASP.NET MVC 앱에서 다음 코드를 사용하여 확인란을 렌더링합니다.

<%= Html.CheckBoxFor(i=>i.ReceiveRSVPNotifications) %>

이제 이것이 확인란 입력 태그와 숨겨진 입력 태그를 모두 렌더링한다는 것을 알았습니다 . 내가 겪고있는 문제는 FormCollection을 사용하여 확인란에서 값을 검색하려고 할 때입니다.

FormValues["ReceiveRSVPNotifications"]

"true, false"값을 얻습니다. 렌더링 된 HTML을 보면 다음을 볼 수 있습니다.

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

따라서 FormValues ​​컬렉션은 이름이 같기 때문에이 두 값을 결합하는 것으로 보입니다.

어떤 아이디어?


여기를보세요 :

http://forums.asp.net/t/1314753.aspx

이것은 버그가 아니며 실제로 Ruby on Rails와 MonoRail이 사용하는 것과 동일한 접근 방식입니다.

확인란이있는 양식을 제출하면 확인란이 선택된 경우에만 값이 게시됩니다. 따라서 확인란을 선택하지 않으면 많은 상황에서 false를 보내려고 할 때 서버로 아무것도 보내지 않습니다. 숨겨진 입력은 확인란과 이름이 같으므로 확인란이 선택되어 있지 않으면 여전히 서버에 'false'가 전송됩니다.

확인란을 선택하면 ModelBinder가 자동으로 'true, false'에서 'true'를 추출합니다.


나는 Shawn (위)과 같은 문제가있었습니다. 이 접근 방식은 POST에는 좋을 수 있지만 실제로 GET에는 짜증이납니다. 따라서 숨겨진 필드를 뛰어 넘는 간단한 Html 확장을 구현했습니다.

public static MvcHtmlString BasicCheckBoxFor<T>(this HtmlHelper<T> html, 
                                                Expression<Func<T, bool>> expression,
                                                object htmlAttributes = null)
{
    var result = html.CheckBoxFor(expression).ToString();
    const string pattern = @"<input name=""[^""]+"" type=""hidden"" value=""false"" />";
    var single = Regex.Replace(result, pattern, "");
    return MvcHtmlString.Create(single);
}

내가 지금 가지고있는 문제는 코드를 깨기 위해 MVC 프레임 워크를 변경하고 싶지 않다는 것입니다. 따라서이 새로운 계약을 설명하는 테스트 범위가 있는지 확인해야합니다.


이 대체 방법을 사용하여 GET 양식의 확인란을 렌더링합니다.

/// <summary>
/// Renders checkbox as one input (normal Html.CheckBoxFor renders two inputs: checkbox and hidden)
/// </summary>
public static MvcHtmlString BasicCheckBoxFor<T>(this HtmlHelper<T> html, Expression<Func<T, bool>> expression, object htmlAttributes = null)
{
    var tag = new TagBuilder("input");

    tag.Attributes["type"] = "checkbox";
    tag.Attributes["id"] = html.IdFor(expression).ToString();
    tag.Attributes["name"] = html.NameFor(expression).ToString();
    tag.Attributes["value"] = "true";

    // set the "checked" attribute if true
    ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
    if (metadata.Model != null)
    {
        bool modelChecked;
        if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
        {
            if (modelChecked)
            {
                tag.Attributes["checked"] = "checked";
            }
        }
    }

    // merge custom attributes
    tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));

    var tagString = tag.ToString(TagRenderMode.SelfClosing);
    return MvcHtmlString.Create(tagString);
}

그것은 비슷 크리스 켐프 이 하나를 제외하고는 잘 작동됩니다의 방법, 사용하지 않는 기본 CheckBoxForRegex.Replace. 원래 Html.CheckBoxFor방법 의 출처를 기반으로합니다 .


추가 입력 태그 의 소스 코드는 다음과 같습니다 . Microsoft는이 문제를 정확하게 해결하는 의견을 포함시킬만큼 친절했습니다.

if (inputType == InputType.CheckBox)
{
    // Render an additional <input type="hidden".../> for checkboxes. This
    // addresses scenarios where unchecked checkboxes are not sent in the request.
    // Sending a hidden input makes it possible to know that the checkbox was present
    // on the page when the request was submitted.
    StringBuilder inputItemBuilder = new StringBuilder();
    inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));

    TagBuilder hiddenInput = new TagBuilder("input");
    hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
    hiddenInput.MergeAttribute("name", fullName);
    hiddenInput.MergeAttribute("value", "false");
    inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
    return MvcHtmlString.Create(inputItemBuilder.ToString());
}

가장 간단한 해결책은 다음과 같이 INPUT 요소를 직접 렌더링하는 것입니다.

<input type="checkbox" 
       id="<%=Html.IdFor(i => i.ReceiveRSVPNotifications)%>"
       name="<%=Html.NameFor(i => i.ReceiveRSVPNotifications)%>"
       value="true"
       checked="<%=Model.ReceiveRSVPNotifications ? "checked" : String.Empty %>" />

In Razor syntax it is even easier, because the 'checked' attribute is directly rendered with a "checked" value when given a 'true' server-side value.

참고URL : https://stackoverflow.com/questions/2860940/why-does-the-checkboxfor-render-an-additional-input-tag-and-how-can-i-get-the-v

반응형