【问题标题】:How to handle Booleans/CheckBoxes in ASP.NET MVC 2 with DataAnnotations?如何使用 DataAnnotations 处理 ASP.NET MVC 2 中的布尔值/复选框?
【发布时间】: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 为空,它也不会工作,因为编译器会喊

“模板只能用于字段访问、属性访问、一维数组索引或单参数自定义索引器表达式。”

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

【问题讨论】:

    标签: asp.net-mvc validation checkbox data-annotations


    【解决方案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 之间”。

    【讨论】:

    • 对我来说很好,我不认为它是一个黑客
    • 您可能需要添加客户端代码验证才能使其正常工作。 &lt;script&gt; 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); } } &lt;/script&gt;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://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");
      

      【讨论】:

        【解决方案9】:

        对于那些在客户端验证时遇到困难的人(以前是我):确保你也有

        1. 包含 在视图中的表单之前
        2. 使用
        3. 创建了一个 DataAnnotationsModelValidator,它返回具有自定义验证类型的规则
        4. 在 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 开头

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-02-14
                • 2010-12-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-11-08
                相关资源
                最近更新 更多