使用数据注释验证小数值保留两位小数?

24

我在我的视图模型中有这个:

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

我想验证用户输入的小数位不超过两位。所以我想要:

有效值: 12, 12.3, 12.34

无效值: 12., 12.345

是否有一种方法可以使用数据注释进行验证?

8个回答

35
你可以使用RegularExpression属性,配合正则表达式来匹配你的标准。这个网站上有很多涉及数字的表达式,我相信其中一个会符合你的需求。这是链接
以下是一个起点,虽然它可能没有你想要的那么全面(需要小数点前至少有一个数字):
[RegularExpression(@"\d+(\.\d{1,2})?", ErrorMessage = "Invalid price")]

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


2
这对于小数分隔符不是句点(.)的语言无效,例如逗号(14,6),因为RegularExpression使用当前区域设置将十进制转换为字符串。 - jahav
如何看待 ^\d*(\.|,|(\.\d{1,2})|(,\d{1,2}))?$ 这个正则表达式,它同时支持点号和逗号,并且允许小数点前没有数字或小数点后没有数字。 - helrich
由于某种原因,给定的正则表达式允许我插入多个小数点,例如:1.22.3.44。 - Storm
1
@jahav,请查看franck-duhaupas的答案,他解决了你的问题! - Yanal-Yves Fargialla

18
[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}$。 - Appetere
2
抱歉,我的意思是^\d+.?\d{0,5}$,其中'?'表示只允许0或1次重复。 - Appetere
这实际上不允许没有小数位的值,例如 10但是它允许带有点的无小数位:10. - Mathew Thompson

6
您还可以创建自己的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;}         

在我看来,它可以精确到小数点后一位。


3

我和提问者遇到了相同的情况,但是提供的答案并不能解决以下所有情况:

12、12.3 和 12.34

为了解决这个问题,我们使用以下正则表达式:

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

3
为了让它在小数分隔符为除点(.)以外的其他语言中正常工作:
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; }

2

mattytommo类似。您需要转义“.” - 否则将接受任何字符。

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

2
您可以使用正则表达式,并使用RegularExpression属性应用它来进行此验证。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接