如何使用DataAnnotations在ASP.NET MVC 2中处理Booleans / CheckBoxes?

我有一个像这样的视图模型:

public class SignUpViewModel { [Required(ErrorMessage = "Bitte lesen und akzeptieren Sie die AGB.")] [DisplayName("Ich habe die AGB gelesen und akzeptiere diese.")] public bool AgreesWithTerms { get; set; } } 

视图标记代码:

 <%= Html.CheckBoxFor(m => m.AgreesWithTerms) %> <%= Html.LabelFor(m => m.AgreesWithTerms)%> 

结果:

没有validation执行。 到目前为止没关系,因为bool是一个值types,从不为空。 但即使我使AgreesWithTerms为空,它也不会工作,因为编译器喊

“模板只能用于字段访问,属性访问,单维数组索引或单参数自定义索引器expression式。

那么,处理这个问题的正确方法是什么呢?

我的解决scheme如下(这与已经提交的答案没有多大区别,但我相信它的名字更好):

 /// <summary> /// Validation attribute that demands that a boolean value must be true. /// </summary> [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class MustBeTrueAttribute : ValidationAttribute { public override bool IsValid(object value) { return value != null && value is bool && (bool)value; } } 

那么你可以在你的模型中像这样使用它:

 [MustBeTrue(ErrorMessage = "You must accept the terms and conditions")] [DisplayName("Accept terms and conditions")] public bool AcceptsTerms { get; set; } 

我将为Server和Client端创build一个validation器。 使用MVC和不显眼的表单validation,可以简单地通过执行以下操作来实现:

首先,在您的项目中创build一个类来执行服务器端validation,如下所示:

 public class EnforceTrueAttribute : ValidationAttribute, IClientValidatable { public override bool IsValid(object value) { if (value == null) return false; if (value.GetType() != typeof(bool)) throw new InvalidOperationException("can only be used on boolean properties."); return (bool)value == true; } public override string FormatErrorMessage(string name) { return "The " + name + " field must be checked in order to continue."; } public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { yield return new ModelClientValidationRule { ErrorMessage = String.IsNullOrEmpty(ErrorMessage) ? FormatErrorMessage(metadata.DisplayName) : ErrorMessage, ValidationType = "enforcetrue" }; } } 

在此之后,在模型中注释相应的属性:

 [EnforceTrue(ErrorMessage=@"Error Message")] public bool ThisMustBeTrue{ get; set; } 

最后,通过将以下脚本添加到您的视图来启用客户端validation:

 <script type="text/javascript"> jQuery.validator.addMethod("enforcetrue", function (value, element, param) { return element.checked; }); jQuery.validator.unobtrusive.adapters.addBool("enforcetrue"); </script> 

注意:我们已经创build了一个方法GetClientValidationRules ,它将注释从我们的模型中推送到视图中。

我通过创build一个自定义属性得到它:

 public class BooleanRequiredAttribute : RequiredAttribute { public override bool IsValid(object value) { return value != null && (bool) value; } } 
 [Compare("Remember", ErrorMessage = "You must accept the terms and conditions")] public bool Remember { get; set; } 

这可能是一个“黑客”,但你可以使用内置的Range属性:

 [Display(Name = "Accepted Terms Of Service")] [Range(typeof(bool), "true", "true")] public bool Terms { get; set; } 

唯一的问题是“警告”string将会显示“FIELDNAME必须介于真与假之间”。

“必需”是错误的validation,在这里。 你想要的东西类似于“必须有值真”,这是不一样的“必需”。 怎么样使用像这样的东西:

 [RegularExpression("^true")] 

我的解决scheme是布尔值的这个简单的自定义属性:

 public class BooleanAttribute : ValidationAttribute { public bool Value { get; set; } public override bool IsValid(object value) { return value != null && value is bool && (bool)value == Value; } } 

那么你可以在你的模型中像这样使用它:

 [Required] [Boolean(Value = true, ErrorMessage = "You must accept the terms and conditions")] [DisplayName("Accept terms and conditions")] public bool AcceptsTerms { get; set; } 

我只是利用现有的解决scheme,并将它们放在一个单一的答案中,以便进行服务器端和客户端validation。

要应用于build模属性以确保bool值必须为真:

 /// <summary> /// Validation attribute that demands that a <see cref="bool"/> value must be true. /// </summary> /// <remarks>Thank you <c>http://stackoverflow.com/a/22511718</c></remarks> [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class MustBeTrueAttribute : ValidationAttribute, IClientValidatable { /// <summary> /// Initializes a new instance of the <see cref="MustBeTrueAttribute" /> class. /// </summary> public MustBeTrueAttribute() : base(() => "The field {0} must be checked.") { } /// <summary> /// Checks to see if the given object in <paramref name="value"/> is <c>true</c>. /// </summary> /// <param name="value">The value to check.</param> /// <returns><c>true</c> if the object is a <see cref="bool"/> and <c>true</c>; otherwise <c>false</c>.</returns> public override bool IsValid(object value) { return (value as bool?).GetValueOrDefault(); } /// <summary> /// Returns client validation rules for <see cref="bool"/> values that must be true. /// </summary> /// <param name="metadata">The model metadata.</param> /// <param name="context">The controller context.</param> /// <returns>The client validation rules for this validator.</returns> public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { if (metadata == null) throw new ArgumentNullException("metadata"); if (context == null) throw new ArgumentNullException("context"); yield return new ModelClientValidationRule { ErrorMessage = FormatErrorMessage(metadata.DisplayName), ValidationType = "mustbetrue", }; } } 

要包含的JavaScript使用不显眼的validation。

 jQuery.validator.addMethod("mustbetrue", function (value, element) { return element.checked; }); jQuery.validator.unobtrusive.adapters.addBool("mustbetrue"); 

对于在客户端(以前为我)进行validation时遇到问题的人,请确保您也有

  1. 包括<%Html.EnableClientValidation(); %>在视图中的表单之前
  2. 对于该字段使用<%= Html.ValidationMessage或Html.ValidationMessageFor
  3. 创build一个DataAnnotationsModelValidator,它返回一个自定义validationtypes的规则
  4. 在Global.Application_Start中注册派生自DataAnnotationsModelValidator的类

http://www.highoncoding.com/Articles/729_Creating_Custom_Client_Side_Validation_in_ASP_NET_MVC_2_0.aspx

是一个很好的教程做这个, 但错过了第4步。

这样做的正确方法是检查types!

 [Range(typeof(bool), "true", "true", ErrorMessage = "You must or else!")] public bool AgreesWithTerms { get; set; } 

在这里find更完整的解决scheme(服务器和客户端validation):

http://blog.degree.no/2012/03/validation-of-required-checkbox-in-asp-net-mvc/#comments

添加[RegularExpression]就足够了:

 [DisplayName("I accept terms and conditions")] [RegularExpression("True", ErrorMessage = "You must accept the terms and conditions")] public bool AgreesWithTerms { get; set; } 

注 – “真”必须以大写T开头