如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?
我有一个像这样的视图模型:
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 是一个值类型并且永远不会为 null。但即使我将 AgreesWithTerms 设置为可为空,它也不起作用,因为编译器会喊
“模板只能与字段访问、属性访问、单维数组索引或单参数自定义索引器表达式一起使用。”
那么,处理这个问题的正确方法是什么?
I've got a view model like this:
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; }
}
The view markup code:
<%= Html.CheckBoxFor(m => m.AgreesWithTerms) %>
<%= Html.LabelFor(m => m.AgreesWithTerms)%>
The result:
No validation is executed. That's okay so far because bool is a value type and never null. But even if I make AgreesWithTerms nullable it won't work because the compiler shouts
"Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions."
So, what's the correct way to handle this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(13)
我会为服务器端和客户端创建一个验证器。使用 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
,它将我们的注释从模型推送到视图。
我只是充分利用现有的解决方案,并将其组合成一个单一的答案,以允许服务器端和客户端验证。
应用于对属性进行建模以确保 bool 值必须为 true:
/// <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 以利用不显眼的验证。
jQuery.validator.addMethod("mustbetrue", function (value, element) {
return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("mustbetrue");
我的解决方案是这个简单的布尔值自定义属性:
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; }
对于在客户端验证方面遇到困难的人(以前是我):请确保您还包含
- <% Html.EnableClientValidation(); %>在视图中的表单之前
- 使用 <%= Html.ValidationMessage 或 Html.ValidationMessageFor 作为字段
- 创建了一个 DataAnnotationsModelValidator,它返回具有自定义验证类型的规则
- 中注册了从 DataAnnotationsModelValidator 派生的类
在 Global.Application_Start http://www.highoncoding.com/Articles/729_Creating_Custom_Client_Side_Validation_in_ASP_NET_MVC_2_0.aspx
是一个很好的教程,但错过了第 4 步。
在这里找到了更完整的解决方案(服务器端和客户端验证):
http://blog. Degree.no/2012/03/validation-of-required-checkbox-in-asp-net-mvc/#comments
如果您使用 s1mm0t 针对 .NET Core 6 及更高版本的答案您还需要添加所需的标记,因此:
Register.cshtml.cs:
public class RegisterModel : PageModel{
...
/// <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;
}
}
...
}
和
public class InputModel{
...
[Required]
[MustBeTrue(ErrorMessage = "You must accept the terms and conditions\n")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
}
Register.cshtml:
<p>
<input id="AcceptTermsCheckbox" asp-for="Input.AcceptsTerms" />
<label asp-for="Input.AcceptsTerms"></label>
<span asp-validation-for="Input.AcceptsTerms" class="text-danger"></span>
By creating an account you confirm that you have read and agree with our Terms & Conditions and Privacy Policy
</p>
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
我的解决方案如下(与已经提交的答案没有太大不同,但我相信它的命名更好):
然后您可以在模型中像这样使用它:
My Solution is as follows (it's not much different to the answers already submitted, but I believe it's named better):
Then you can use it like this in your model: