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

发布于 08-21 07:43 字数 603 浏览 9 评论 0原文

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

小兔几2024-08-28 07:43:26

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

/// <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; }

My Solution is as follows (it's not much different to the answers already submitted, but I believe it's named better):

/// <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;
    }
}

Then you can use it like this in your model:

[MustBeTrue(ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
若言繁花未落2024-08-28 07:43:26

我会为服务器端和客户端创建一个验证器。使用 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 ,它将我们的注释从模型推送到视图。

I would create a validator for both Server AND Client side. Using MVC and unobtrusive form validation, this can be achieved simply by doing the following:

Firstly, create a class in your project to perform the server side validation like so:

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"
        };
    }
}

Following this, annotate the appropriate property in your model:

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

And Finally, enable client side validation by adding the following script to your View:

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

Note: We already created a method GetClientValidationRules which pushes our annotation to the view from our model.

冷默言语2024-08-28 07:43:26

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

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

I got it by creating a custom attribute:

public class BooleanRequiredAttribute : RequiredAttribute 
{
    public override bool IsValid(object value)
    {
        return value != null && (bool) value;
    }
}
岁吢2024-08-28 07:43:26

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

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

唯一的问题是“警告”字符串会说“FIELDNAME 必须在 True 和 true 之间”。

This might be a "hack" but you can use the built in Range attribute:

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

The only problem is the "warning" string will say "The FIELDNAME must be between True and true".

北城孤痞2024-08-28 07:43:26
[Compare("Remember", ErrorMessage = "You must accept the terms and conditions")]
public bool Remember { get; set; }
[Compare("Remember", ErrorMessage = "You must accept the terms and conditions")]
public bool Remember { get; set; }
会傲2024-08-28 07:43:26

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

应用于对属性进行建模以确保 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");

I'm just taking the best of the existing solutions and putting it together into a single answer that allows for both server side and client side validation.

The to apply to model a properties to ensure a bool value must be 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",
            };
    }
}

The JavaScript to include to make use of unobtrusive validation.

jQuery.validator.addMethod("mustbetrue", function (value, element) {
    return element.checked;
});
jQuery.validator.unobtrusive.adapters.addBool("mustbetrue");
束缚m2024-08-28 07:43:26

这里的“必需”是错误的验证。您想要类似于“必须具有 true 值”的内容,这与“必需”不同。使用类似的东西怎么样:

[RegularExpression("^true")]

"Required" is the wrong validation, here. You want something akin to "Must have the value true," which is not the same as "Required". What about using something like:

[RegularExpression("^true")]

?

把梦留给海2024-08-28 07:43:26

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

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; }

My solution is this simple custom attribute for boolean values:

public class BooleanAttribute : ValidationAttribute
{
    public bool Value
    {
        get;
        set;
    }

    public override bool IsValid(object value)
    {
        return value != null && value is bool && (bool)value == Value;
    }
}

Then you can use it like this in your model:

[Required]
[Boolean(Value = true, ErrorMessage = "You must accept the terms and conditions")]
[DisplayName("Accept terms and conditions")]
public bool AcceptsTerms { get; set; }
暗地喜欢2024-08-28 07:43:26

正确的方法是检查类型!

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

The proper way to do this is to check the type!

[Range(typeof(bool), "true", "true", ErrorMessage = "You must or else!")]
public bool AgreesWithTerms { get; set; }
墟烟2024-08-28 07:43:26

对于在客户端验证方面遇到困难的人(以前是我):请确保您还包含

  1. <% Html.EnableClientValidation(); %>在视图中的表单之前
  2. 使用 <%= Html.ValidationMessage 或 Html.ValidationMessageFor 作为字段
  3. 创建了一个 DataAnnotationsModelValidator,它返回具有自定义验证类型的规则
  4. 中注册了从 DataAnnotationsModelValidator 派生的类

在 Global.Application_Start http://www.highoncoding.com/Articles/729_Creating_Custom_Client_Side_Validation_in_ASP_NET_MVC_2_0.aspx

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

For people who are having trouble getting this working for validation on the client side (formerly me): make sure you have also

  1. Included <% Html.EnableClientValidation(); %> before the form in the view
  2. Used <%= Html.ValidationMessage or Html.ValidationMessageFor for the field
  3. Created a DataAnnotationsModelValidator which returns a rule with a custom validation type
  4. Registered the class deriving from DataAnnotationsModelValidator in the Global.Application_Start

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

is a good tutorial on doing this, but misses step 4.

丶情人眼里出诗心の2024-08-28 07:43:26

在这里找到了更完整的解决方案(服务器端和客户端验证):

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

Found a more complete solution here (both server and client side validation):

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

染火枫林2024-08-28 07:43:26

添加 [RegularExpression] 就足够了:

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

注意 - “True”必须以大写 T 开头

It's enough to add [RegularExpression]:

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

Note - "True" must start with capital T

美人骨2024-08-28 07:43:26

如果您使用 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>

If you are using s1mm0t's answer for .NET Core 6 and higher you need to also add a required tag, so:

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;
            }
        }
    ...

}

and

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文