C# 所需的复选框验证与Html相反。CheckBoxFor

C# 所需的复选框验证与Html相反。CheckBoxFor,c#,html,asp.net-mvc,razor,checkbox,C#,Html,Asp.net Mvc,Razor,Checkbox,在提交页面之前,我有一个复选框验证。但事实恰恰相反。当我选中该框而不是相反时,它会显示错误消息。我不知道我哪里做错了 我的视图模型 [Display(Name = "Terms and Conditions")] [Range(typeof(bool), "true", "true", ErrorMessage = "Please accept Terms & Conditions")] public bool IsTermsAccepted { get; set; } 我的看法 &l

在提交页面之前,我有一个复选框验证。但事实恰恰相反。当我选中该框而不是相反时,它会显示错误消息。我不知道我哪里做错了

我的视图模型

[Display(Name = "Terms and Conditions")]
[Range(typeof(bool), "true", "true", ErrorMessage = "Please accept Terms & Conditions")]
public bool IsTermsAccepted { get; set; }
我的看法

<div class="row col-lg-offset-2 top-buffer">
                @Html.CheckBoxFor(model => model.IsTermsAccepted)
                @Html.LabelFor(model => model.IsTermsAccepted)
            <br>@Html.ValidationMessageFor(model => model.IsTermsAccepted)
        </div>

@CheckBoxFor(model=>model.IsTermsAccepted)
@LabelFor(model=>model.IsTermsAccepted)

@Html.ValidationMessageFor(model=>model.IsTermsAccepted)
谢谢你抽出时间

伊迪丝1:我跟他一模一样

Edit2:我可以通过添加一个简单的脚本来解决这个问题(如上面提到的链接所示)


//扩展范围验证器方法以区别对待复选框
var defaultRangeValidator=$.validator.methods.range;
$.validator.methods.range=函数(值、元素、参数){
如果(element.type==='checkbox'){
//如果是复选框,则选中后返回true
返回元素。已选中;
}否则{
//否则,运行默认的验证函数
返回defaultRangeValidator.call(this,value,element,param);
}
}

您需要了解
复选框for
在ASP.NET MVC中是如何工作的,以及复选框在HTML中是如何工作的(请参阅我对这个问题的回答:)

  • 如果未选中HTML复选框,则不会在
    post
    请求正文中发布其值
  • 因此,为了区分“未选中复选框”和“排除复选框”之间的区别,您需要包含一个明确的“false”值,如
    ,其属性值与复选框输入的属性值相同
  • ASP.NET MVC为您做了这件事:
    Html.CheckBoxFor()
    同时呈现
    
    
    • 如果查看页面的呈现HTML,您将同时看到它们
因此,当您提交选中的复选框时,浏览器实际上正在发送两个值:
true
false
。是
“false”
值导致
范围
验证器失败,即使它也发送了
真值

但是,
RangeValidatorAttribute
不够智能,无法处理使用
CheckBoxFor
设置的布尔ViewModel属性的这种特定情况

据我所知,没有处理这种情况的内置
DataAnnotation
属性-您需要在控制器操作中自己实现它,如下所示:

[HttpPost]
public IHttpActionResult Foo(FooViewModel model) {

    if( !model.IsTermsAccepted ) {

        this.ModelState.AddModelError( nameof(model.IsTermsAccepted), "you must accept the terms." );
        return this.View( model );
    }

}
…或者您可以尝试自己实现一个新的验证属性,它需要这样做

注意它源自
Required
属性,因为您需要确保属性在请求正文中具有值(即复选框包含在响应中,带有隐藏输入),并且
true
值存在

[AttributeUsageAttribute(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
class CheckboxIsCheckedAttribute : RequiredAttribute {

    public override bool IsValid(Object value) {

        Boolean isRequiredValid = base.IsValid( value );
        if( !isRequiredValid ) return false;

        return (value as Boolean) == true;
    }
}

很好的解释,但请注意,它不应该派生自
RequiredAttribute
,而应该派生自
ValidationAttribute
(因为默认情况下它是
bool
必需的,如果响应中没有值,则已经添加了验证错误)。此外,如果您从
RequiredAttribute
派生,它还必须在
global.asax
中注册(dupe中的dazbradbury答案是正确的方法,并提供客户端验证)
[AttributeUsageAttribute(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
class CheckboxIsCheckedAttribute : RequiredAttribute {

    public override bool IsValid(Object value) {

        Boolean isRequiredValid = base.IsValid( value );
        if( !isRequiredValid ) return false;

        return (value as Boolean) == true;
    }
}