的ASP.NET MVC 3 CheckBoxFor方法输出隐藏字段,当复选框被与选定的真禁用的隐藏

2019-06-25 10:53发布

CheckBoxFor(T => t.boolValue,新的{禁用= “禁用”})方法以呈现一个复选框,以禁用模式。

该方法呈现一个隐藏字段为好。

我的问题是,为什么这个隐藏字段为残疾复选框虚假的价值? 我相信隐藏字段的目的是为了有超过默认的复选框行为的一些额外的行为

有没有办法让这个隐藏字段的值是基于即使在禁用模式复选框的状态,以覆盖默认的MVC功能?

Answer 1:

隐藏字段用于复选框值绑定到布尔属性。 问题是,如果没有选中复选框,没有什么是发送到服务器,所以ASP.NET MVC使用这个隐藏字段发送虚假并绑定到相应的布尔字段。 您不能修改比写一个自定义的助手等这种行为。

这是说,而不是使用disabled="disabled"使用readonly="readonly"的复选框。 这样,您将保持相同的期望的行为,该用户不能修改它的价值,但除了它的值将被发送到表单时提交的服务器:

@Html.CheckBoxFor(x => x.Something, new { @readonly = "readonly" })

更新:

正如在评论中指出部分的readonly属性不与谷歌Chrome浏览器。 另一种可能性是用另一个隐藏字段和禁用复选框:

@Html.HiddenFor(x => x.Something)
@Html.CheckBoxFor(x => x.Something, new { disabled = "disabled" })

更新2:

这是一个完整的测试用例与额外的隐藏字段。

模型:

public class MyViewModel
{
    public bool Foo { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel { Foo = true });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return Content(model.Foo.ToString());
    }
}

视图:

@model MyViewModel

@using (Html.BeginForm())
{
    @Html.HiddenFor(x => x.Foo)
    @Html.CheckBoxFor(x => x.Foo, new { disabled = "disabled" })
    <button type="submit">OK</button>
}

当表单提交的富属性的值是true 。 我已经与所有主要的浏览器(Chrome浏览器,FF,IE)进行测试。



Answer 2:

我发现在查询字符串所添加的参数看起来很乱,让人觉得,我们作为开发商做错了什么。 所以,我使出创造我自己的InputExtensions类的极端方法,让我对我是否要隐藏输入要呈现与否决定。

下面是我创建(基于现有的MVC代码保持完全兼容)的InputExtensions类:

public static class InputExtensions
{
    //
    // Checkboxes
    //

    public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, bool>> expression, bool renderHiddenInput)
    {
        if (renderHiddenInput)
        {
            return System.Web.Mvc.Html.InputExtensions.CheckBoxFor(htmlHelper, expression);
        }
        return CheckBoxFor(htmlHelper, expression, false);
    }

    public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, bool>> expression, object htmlAttributes, bool renderHiddenInput)
    {
        if (renderHiddenInput)
        {
            return System.Web.Mvc.Html.InputExtensions.CheckBoxFor(htmlHelper, expression, htmlAttributes);
        }
        return CheckBoxFor(htmlHelper, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), false);
    }

    public static MvcHtmlString CheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, bool>> expression, IDictionary<string, object> htmlAttributes,
        bool renderHiddenInput)
    {
        if (renderHiddenInput)
        {
            return System.Web.Mvc.Html.InputExtensions.CheckBoxFor(htmlHelper, expression, htmlAttributes);
        }

        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
        bool? isChecked = null;
        if (metadata.Model != null)
        {
            bool modelChecked;
            if (Boolean.TryParse(metadata.Model.ToString(), out modelChecked))
            {
                isChecked = modelChecked;
            }
        }

        return CheckBoxHelper(htmlHelper, metadata, ExpressionHelper.GetExpressionText(expression), isChecked, htmlAttributes);
    }

    private static MvcHtmlString CheckBoxHelper(HtmlHelper htmlHelper, ModelMetadata metadata, string name, bool? isChecked, IDictionary<string, object> htmlAttributes)
    {
        RouteValueDictionary attributes = ToRouteValueDictionary(htmlAttributes);

        bool explicitValue = isChecked.HasValue;
        if (explicitValue)
        {
            attributes.Remove("checked"); // Explicit value must override dictionary
        }

        return InputHelper(htmlHelper,
                           InputType.CheckBox,
                           metadata,
                           name,
                           value: "true",
                           useViewData: !explicitValue,
                           isChecked: isChecked ?? false,
                           setId: true,
                           isExplicitValue: false,
                           format: null,
                           htmlAttributes: attributes);
    }

    //
    // Helper methods
    //

    private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format, IDictionary<string, object> htmlAttributes)
    {
        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
        if (string.IsNullOrEmpty(fullName))
        {
            throw new ArgumentException("Value cannot be null or empty.", "name");
        }

        var tagBuilder = new TagBuilder("input");
        tagBuilder.MergeAttributes(htmlAttributes);
        tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
        tagBuilder.MergeAttribute("name", fullName, true);

        string valueParameter = htmlHelper.FormatValue(value, format);
        var usedModelState = false;

        bool? modelStateWasChecked = GetModelStateValue(htmlHelper.ViewData, fullName, typeof(bool)) as bool?;
        if (modelStateWasChecked.HasValue)
        {
            isChecked = modelStateWasChecked.Value;
            usedModelState = true;
        }
        if (!usedModelState)
        {
            string modelStateValue = GetModelStateValue(htmlHelper.ViewData, fullName, typeof(string)) as string;
            if (modelStateValue != null)
            {
                isChecked = string.Equals(modelStateValue, valueParameter, StringComparison.Ordinal);
                usedModelState = true;
            }
        }
        if (!usedModelState && useViewData)
        {
            isChecked = EvalBoolean(htmlHelper.ViewData, fullName);
        }
        if (isChecked)
        {
            tagBuilder.MergeAttribute("checked", "checked");
        }
        tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);

        if (setId)
        {
            tagBuilder.GenerateId(fullName);
        }

        // If there are any errors for a named field, we add the css attribute.
        ModelState modelState;
        if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
        {
            if (modelState.Errors.Count > 0)
            {
                tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
            }
        }

        tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));

        return MvcHtmlString.Create(tagBuilder.ToString(TagRenderMode.SelfClosing));
    }

    private static RouteValueDictionary ToRouteValueDictionary(IDictionary<string, object> dictionary)
    {
        return dictionary == null ? new RouteValueDictionary() : new RouteValueDictionary(dictionary);
    }

    private static object GetModelStateValue(ViewDataDictionary viewData, string key, Type destinationType)
    {
        ModelState modelState;
        if (viewData.ModelState.TryGetValue(key, out modelState))
        {
            if (modelState.Value != null)
            {
                return modelState.Value.ConvertTo(destinationType, culture: null);
            }
        }
        return null;
    }

    private static bool EvalBoolean(ViewDataDictionary viewData, string key)
    {
        return Convert.ToBoolean(viewData.Eval(key), CultureInfo.InvariantCulture);
    }
}

然后,你可以调用像这样的方法:

@Html.CheckBoxFor(t => t.boolValue, new { disabled="disabled" }, false)


Answer 3:

这里是一个快速的提示,我发现:如果您在对象上的布尔值设置为默认值。 这是可能写出来的标签以该值为真/假(此值应该是默认的布尔值的对象的对面)

<input type="checkbox" name="IsAllDayEvent" value="true" id="IsAllDayEvent" />

如果复选框被选中的值时,才会发送,所以它的工作原理。



Answer 4:

虽然达林的答案是完全正常的,有确保残疾人复选框后背上预期的另一种方式。

该解决方案也将在复选框被禁用基于有条件上的属性在一个模型中,或启用了基于用户选择或客户端/禁用客户端检索到的数据的情况下工作。

你可以把你的观点很简单:(设置在这里禁用可选)

@Html.CheckBoxFor(m => m.Something, new { id = "somethingCheckbox", disabled = "disabled" })

这种意愿,达林提到产生一个额外的隐藏输入字段设置为false,使该复选框值会后回也当不选中的复选框。 因此,我们知道Something字段始终后回不管复选框被选中与否,禁用。 唯一的问题是,如果复选框被禁用,它会随时回来后为False

我们可以在提交之前解决这个问题有一些JavaScript后处理。 在我的情况下,代码看起来类似的规定:

var dataToPost = $form.serializeArray();

if (dataToPost != null) {
    for (var i = 0; i < dataToPost.length; i++) {
        if (dataToPost[i].name === "Something") {
            dataToPost[i].value = $("#somethingCheckbox").attr("checked") === "checked";
            }
        }
    }  
$.post($form.attr("action"), dataToPost)

您可能需要修改您的方案,但你应该明白我的意思。



文章来源: Asp .net mvc 3 CheckBoxFor method outputs hidden field, that hidden field value is false when checkbox is disabled with selected true