如何使用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时遇到问题的人,请确保您也有
- 包括<%Html.EnableClientValidation(); %>在视图中的表单之前
- 对于该字段使用<%= Html.ValidationMessage或Html.ValidationMessageFor
- 创build一个DataAnnotationsModelValidator,它返回一个自定义validationtypes的规则
- 在Global.Application_Start中注册派生自DataAnnotationsModelValidator的类
是一个很好的教程做这个, 但错过了第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开头