如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?
Posted
技术标签:
【中文标题】如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?【英文标题】:How to handle Booleans/CheckBoxes in ASP.NET MVC 2 with DataAnnotations? 【发布时间】:2011-01-15 18:07:31 【问题描述】:我有一个这样的视图模型:
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)%>
结果:
不执行验证。到目前为止没关系,因为 bool 是一种值类型,并且永远不会为空。但即使我让 AgreesWithTerms 为空,它也不会工作,因为编译器会喊
“模板只能用于字段访问、属性访问、一维数组索引或单参数自定义索引器表达式。”
那么,处理这个问题的正确方法是什么?
【问题讨论】:
【参考方案1】:我的解决方案如下(和已经提交的答案差别不大,但我相信命名更好):
/// <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;
【讨论】:
+1:搜索,找到帖子,选择最佳答案(你是对的,你的被评为最佳答案),剪切,粘贴,刷新,问题解决。不到 2 分钟...甜 这似乎不适用于我的 vanilla MVC 2 项目...已知问题? 也是一个很好的例子,如果它似乎对你不起作用,它似乎要等到你的所有其他验证([必需]等......)都为真后再“触发” . 第一个检查(值!= null)甚至可以省略:) 不能在客户端工作?这与仅添加 [Range(1, 1)] 注释相同。【参考方案2】:我将为服务器端和客户端创建一个验证器。使用 MVC 和不显眼的表单验证,只需执行以下操作即可实现:
首先,在您的项目中创建一个类来执行服务器端验证,如下所示:
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;
最后,通过将以下脚本添加到您的视图来启用客户端验证:
<script type="text/javascript">
jQuery.validator.addMethod("enforcetrue", function (value, element, param)
return element.checked;
);
jQuery.validator.unobtrusive.adapters.addBool("enforcetrue");
</script>
注意:我们已经创建了一个方法GetClientValidationRules
,它将注释从我们的模型推送到视图。
【讨论】:
我终于找到了可行的解决方案!其他的不完整(有时JS部分遗漏,有时是错误的)。非常感谢。 @AlexanderProkofyev - 很高兴你发现它有用!我发现了同样的事情,所以一旦我有了解决方案,我想我会发布一个完整的答案。 可能值得注意的是:如果想将 JS 与视图分开,调用 addMethod 和 addBool 函数来设置客户端验证在 document.ready 函数内部不起作用。 太棒了!另外值得注意的是 - 如果它似乎不起作用,则必须通过所有其他验证才能验证此验证。 这应该是公认的答案,上面的一个和接受的一个在客户端不起作用【参考方案3】:我通过创建自定义属性得到它:
public class BooleanRequiredAttribute : RequiredAttribute
public override bool IsValid(object value)
return value != null && (bool) value;
【讨论】:
+1 用于发布您的解决方案,但我仍然认为“必需”是错误的名称。我会叫它BooleanRequireTrueAttribute
什么的。
是的,我同意你的看法。我将它重命名为 BooleanRequireToBeTrueAttribute【参考方案4】:
这可能是一个“hack”,但您可以使用内置的 Range 属性:
[Display(Name = "Accepted Terms Of Service")]
[Range(typeof(bool), "true", "true")]
public bool Terms get; set;
唯一的问题是“警告”字符串会显示“FIELDNAME 必须介于 True 和 true 之间”。
【讨论】:
对我来说很好,我不认为它是一个黑客 您可能需要添加客户端代码验证才能使其正常工作。<script> var defaultRangeValidator = $.validator.methods.range; $.validator.methods.range = function(value, element, param) if(element.type === 'checkbox') return element.checked; else return defaultRangeValidator.call(this, value, element, param); </script>
Read here for more info
客户端不起作用,勾选复选框时显示错误消息【参考方案5】:
[Compare("Remember", ErrorMessage = "You must accept the terms and conditions")]
public bool Remember get; set;
【讨论】:
不错 :) 但我怀疑这在服务器端不起作用?【参考方案6】:这里的“必需”是错误的验证。您想要类似于“必须具有真实值”的内容,这与“必需”不同。使用类似的东西怎么样:
[RegularExpression("^true")]
?
【讨论】:
如果布尔值必须始终为 / 必须为真,那么在您的代码中甚至没有必要。如果Required 属性有助于DB 级别的“NOT NULL”语句,则不需要它,因为保证您具有真值或假值。 @Chris,它将在您的编辑模型上,但不在您的实体上。通常,您不应直接绑定到实体。 @Craig,同意不直接绑定。但是,如果您的域模型对象(实体)有一个属性必须始终为真,那么它就不是一个有用的属性,对吧? 对,但这不是他在这里提议的。 @Peter:检查 POST 包含的内容。写一个比我第一个猜测更好的正则表达式。【参考方案7】:我的解决方案是这个布尔值的简单自定义属性:
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;
【讨论】:
【参考方案8】:我只是充分利用现有解决方案,并将其组合成一个允许服务器端和客户端验证的单一答案。
应用于对属性建模以确保布尔值必须为真:
/// <summary>
/// Validation attribute that demands that a <see cref="bool"/> value must be true.
/// </summary>
/// <remarks>Thank you <c>http://***.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。
jQuery.validator.addMethod("mustbetrue", function (value, element)
return element.checked;
);
jQuery.validator.unobtrusive.adapters.addBool("mustbetrue");
【讨论】:
【参考方案9】:对于那些在客户端验证时遇到困难的人(以前是我):确保你也有
-
包含 在视图中的表单之前
使用
创建了一个 DataAnnotationsModelValidator,它返回具有自定义验证类型的规则
在 Global.Application_Start 中注册了派生自 DataAnnotationsModelValidator 的类
http://www.highoncoding.com/Articles/729_Creating_Custom_Client_Side_Validation_in_ASP_NET_MVC_2_0.aspx
这是一个很好的教程,但错过了第 4 步。
【讨论】:
【参考方案10】:正确的做法是检查类型!
[Range(typeof(bool), "true", "true", ErrorMessage = "You must or else!")]
public bool AgreesWithTerms get; set;
【讨论】:
【参考方案11】:在这里找到了更完整的解决方案(服务器端和客户端验证):
http://blog.degree.no/2012/03/validation-of-required-checkbox-in-asp-net-mvc/#comments
【讨论】:
【参考方案12】:加上[RegularExpression]就够了:
[DisplayName("I accept terms and conditions")]
[RegularExpression("True", ErrorMessage = "You must accept the terms and conditions")]
public bool AgreesWithTerms get; set;
注意 - “真”必须以大写 T 开头
【讨论】:
以上是关于如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 DataAnnotations 来检查一个属性只匹配一个字符串数组
如何覆盖DataAnnotations必需标记以允许条件客户端验证
如何将 DataAnnotations ErrorMessageResourceName 与自定义资源解决方案一起使用