【问题标题】:Validate decimal value to 2 decimal places with data annotations?使用数据注释将十进制值验证为小数点后 2 位?
【发布时间】:2012-03-22 10:43:28
【问题描述】:

我的视图模型中有这个:

[Required(ErrorMessage = "Price is required")]
[Range(0.01, 999999999, ErrorMessage = "Price must be greater than 0.00")]
[DisplayName("Price ($)")]
public decimal Price { get; set; }

我想验证用户输入的小数位数不超过 2 位。所以我想拥有

有效值:12、12.3、12.34

无效值:12.、12.345

有没有办法通过数据注释来验证这一点?

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-3


    【解决方案1】:

    您可以使用 RegularExpression 属性和符合您条件的正则表达式。这里有一大堆涉及数字的表达方式,我相信其中一个会符合要求。这是link

    这将帮助您入门,尽管它可能不像您想要的那样具有包容性(需要至少一位小数点前导):

    [RegularExpression(@"\d+(\.\d{1,2})?", ErrorMessage = "Invalid price")]
    

    请注意,很难发出精确的错误消息,因为您不知道正则表达式的哪一部分匹配失败(例如,字符串“z.22”具有正确的小数位数,但不是一个有效的价格)。

    【讨论】:

    • 这不适用于带有除句点 (.) 以外的小数分隔符的语言,例如逗号 (14,6),因为正则表达式使用当前区域性将十进制转换为字符串。
    • ^\d*(\.|,|(\.\d{1,2})|(,\d{1,2}))?$ 怎么样,它同时使用句点和逗号,也允许在点之前没有前导数字或在点之后没有数字。
    • 由于某种原因,给定的正则表达式允许我插入多个小数点,例如:1.22.3.44
    • @jahav,查看 franck-duhaupas 解决您问题的答案!
    【解决方案2】:
    [RegularExpression(@"^\d+.\d{0,2}$",ErrorMessage = "Price can't have more than 2 decimal places")]
    public decimal Price { get; set; }
    

    这将满足小数点后 0 到 2 位,或者根本没有。

    【讨论】:

    • 您可能想要转义 '.' (这意味着“任何字符”如果没有转义)给 ^\d+\.\d{0,5}$
    • 哎呀,抱歉的意思是 ^\d+\.?\d{0,5}$ 带有 '?'只允许 0 或 1 次重复。
    • 这实际上不允许没有小数位的值,即10但是,它确实允许没有小数位的点:10.
    【解决方案3】:

    您还可以创建自己的 Decimal 验证属性,继承自 RegularExpressionAttribute

     public class DecimalAttribute : RegularExpressionAttribute
     {
        public int DecimalPlaces { get; set; }
        public DecimalAttribute(int decimalPlaces)
            : base(string.Format(@"^\d*\.?\d{{0,{0}}}$", decimalPlaces))
        {
            DecimalPlaces = decimalPlaces;
        }
    
        public override string FormatErrorMessage(string name)
        {
            return string.Format("This number can have maximum {0} decimal places", DecimalPlaces);
        }
     }
    

    并注册它以在 Application_Start() 中启用客户端验证:

    DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(DecimalAttribute), typeof(RegularExpressionAttributeAdapter));
    

    【讨论】:

      【解决方案4】:
      [RegularExpression(@"^\d+(\.\d)?$", ErrorMessage = "It cannot have more than one decimal point value")]
      [Range( 0.1,100)]
      public double xyz{get;set;}         
      

      它适用于我的小数点后一位

      【讨论】:

        【解决方案5】:

        使其适用于带小数点分隔符而非句点 (.) 的语言:

        using System;
        using System.ComponentModel.DataAnnotations;
        using System.Globalization;
        
        /// <summary>
        /// Decimal precision validator data annotation.
        /// </summary>
        [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter)]
        public sealed class DecimalPrecisionAttribute : ValidationAttribute
        {
          private readonly uint _decimalPrecision;
        
          public DecimalPrecisionAttribute(uint decimalPrecision)
          {
            _decimalPrecision = decimalPrecision;
          }
        
          public override bool IsValid(object value)
          {
            return value is null || (value is decimal d && HasPrecision(d, _decimalPrecision));
          }
        
          private static bool HasPrecision(decimal value, uint precision)
          {
            string valueStr = value.ToString(CultureInfo.InvariantCulture);
            int indexOfDot = valueStr.IndexOf('.');
            if (indexOfDot == -1)
            {
              return true;
            }
        
            return valueStr.Length - indexOfDot - 1 <= precision;
          }
        }
        

        用法:

        [Required(ErrorMessage = "Price is required")]
        [DecimalPrecision(2)]
        [DisplayName("Price ($)")]
        public decimal Price { get; set; }
        

        【讨论】:

          【解决方案6】:

          您可以使用正则表达式进行此验证,并将其与 RegularExpression 属性一起应用。

          【讨论】:

            【解决方案7】:

            我遇到了与 OP 相同的情况,但提供的答案并未提供适用于以下所有情况的解决方案:

            12, 12.3 and 12.34

            为此,我们使用以下正则表达式:

            [RegularExpression(@"^\d+(.\d{1,2})?$")]
            

            【讨论】:

              【解决方案8】:

              类似于 ma​​ttytommo。你需要逃避'。' - 否则任何字符都将被接受

              [RegularExpression(@"^\d+(\.\d{1,2})?$")]
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-07-30
                • 2018-03-10
                • 2010-09-14
                • 1970-01-01
                • 2013-07-02
                • 2015-11-18
                • 1970-01-01
                相关资源
                最近更新 更多