如何使用DataAnnotations处理ASP.NET MVC 2中的布尔值/ CheckBox?

asp*_*net 47 validation checkbox asp.net-mvc data-annotations

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

视图标记代码:

<%= Html.CheckBoxFor(m => m.AgreesWithTerms) %>
<%= Html.LabelFor(m => m.AgreesWithTerms)%>
Run Code Online (Sandbox Code Playgroud)

结果:

没有执行验证.到目前为止,这没关系,因为bool是一个值类型,永远不会为null.但即使我使AgreesWithTerms可以为空,它也无法工作,因为编译器大喊大叫

"模板只能用于字段访问,属性访问,单维数组索引或单参数自定义索引器表达式."

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

s1m*_*m0t 91

我的解决方案如下(它与已提交的答案没有太大差别,但我相信它的名字更好):

/// <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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的模型中使用它:

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

  • +1:搜索,发现帖子,选择最佳答案(你是对的,你的名字最好),剪切,粘贴,刷新,问题解决了.不到2分钟......甜蜜 (7认同)
  • 也是一个很好的例子,如果它似乎不适合你,它似乎等到你的所有其他验证([必需]等...)在"触发"之前为真. (2认同)
  • 客户端不工作吗?这与仅放置[Range(1,1)]注释相同。 (2认同)

daz*_*ury 49

我会为服务器和客户端创建一个验证器.使用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"
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

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

[EnforceTrue(ErrorMessage=@"Error Message")]
public bool ThisMustBeTrue{ get; set; }
Run Code Online (Sandbox Code Playgroud)

最后,通过在View中添加以下脚本来启用客户端验证:

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

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

  • 最后我找到了解决方案!其他人不完整(有时JS部分被遗漏,有时候是错误的).非常感谢你. (3认同)

asp*_*net 18

我通过创建自定义属性得到它:

public class BooleanRequiredAttribute : RequiredAttribute 
{
    public override bool IsValid(object value)
    {
        return value != null && (bool) value;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1用于发布您的解决方案,但我仍然认为"必需"是错误的名称.我称之为`BooleanRequireTrueAttribute`或其他东西. (6认同)

Pro*_*ega 6

这可能是"hack",但您可以使用内置的Range属性:

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

唯一的问题是"警告"字符串会说"FIELDNAME必须介于真与真之间".


小智 6

[Compare("Remember", ErrorMessage = "You must accept the terms and conditions")]
public bool Remember { get; set; }
Run Code Online (Sandbox Code Playgroud)


Jam*_*ing 6

我只是充分利用现有的解决方案,并将其组合成一个单一的答案,以允许服务器端和客户端验证。

应用于对属性建模以确保 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",
            };
    }
}
Run Code Online (Sandbox Code Playgroud)

要包含的 JavaScript 以利用不显眼的验证。

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