【问题标题】:Int or Number DataType for DataAnnotation validation attributeDataAnnotation 验证属性的 Int 或 Number DataType
【发布时间】:2021-02-18 05:02:52
【问题描述】:

在我的 MVC3 项目中,我存储了足球/足球/曲棍球/...体育比赛的得分预测。所以我的预测类的属性之一是这样的:

[Range(0, 15, ErrorMessage = "Can only be between 0 .. 15")]
[StringLength(2, ErrorMessage = "Max 2 digits")]
[Remote("PredictionOK", "Predict", ErrorMessage = "Prediction can only be a number in range 0 .. 15")]
public int? HomeTeamPrediction { get; set; }

现在,我还需要更改数据类型的错误消息,在我的例子中是 int。使用了一些默认值 - “HomeTeamPrediction 字段必须是一个数字。”。需要找到一种方法来更改此错误消息。此验证消息似乎也可以预测远程验证。

我尝试过[DataType] 属性,但这似乎不是system.componentmodel.dataannotations.datatype 枚举中的普通数字。

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-3 data-annotations


    【解决方案1】:

    对于任何数字验证,您必须根据您的要求使用不同的不同范围验证:

    对于整数

    [Range(0, int.MaxValue, ErrorMessage = "Please enter valid integer Number")]
    

    浮动

    [Range(0, float.MaxValue, ErrorMessage = "Please enter valid float Number")]
    

    双倍

    [Range(0, double.MaxValue, ErrorMessage = "Please enter valid doubleNumber")]
    

    【讨论】:

    • 在我的上下文中这对我不起作用。如果用户输入 "asdf", [Range(typeof(decimal), "0", "9999.99", ErrorMessage = "Value for {0} must be between {1} and {2}")] 抛出异常。但是,如果我这样做 [Range(typeof(decimal), "0.1", "9999.99", ErrorMessage = "Value for {0} must be between {1} and {2}")] ,错误消息将正常工作。 0 vs 0.1 ,没有意义。也许是错误?
    • 此“整数”验证将非整数值视为有效(例如 0.3)
    【解决方案2】:

    尝试以下正则表达式之一:

    // for numbers that need to start with a zero
    [RegularExpression("([0-9]+)")] 
    
    
    // for numbers that begin from 1
    [RegularExpression("([1-9][0-9]*)")] 
    

    希望对你有帮助:D

    【讨论】:

    • 没有更简单的方法吗?我希望有类似的东西:[Numeric(ErrorMessage = "This field must be a number")]
    • 很遗憾没有。您始终可以编写自己的验证属性。
    • 这是更好的解决方案,因为它涵盖了字符串。 int.MaxValue 只覆盖到2.147.483.647
    • 此正则表达式仅在属性为 int 类型时才有效,如果您使用的是 string 类型的属性,则该正则表达式还将接受 a123 或任何其他具有至少在某个地方有一个数字。要从头到尾验证数字,请使用 ^[0-9]+$ 表示整数或使用 ^[0-9]*\.?[0-9]+$ 表示浮点数
    【解决方案3】:

    在数据标注中使用正则表达式

    [RegularExpression("([0-9]+)", ErrorMessage = "Please enter valid Number")]
    public int MaxJsonLength { get; set; }
    

    【讨论】:

    • 这在问题的上下文中似乎可以正常工作,前提是属性不是 int,而是 string。
    • 为什么在正则表达式两边加上括号?会不会只是[0-9]+
    • 此正则表达式仅在属性为 int 类型时才有效,如果您使用的是 string 类型的属性,则该正则表达式还将接受 a123 或任何其他具有至少在某个地方有一个数字。要从头到尾验证数字,请使用 ^[0-9]+$ 表示整数或 ^[0-9]*\.?[0-9]+$ 表示浮点数
    【解决方案4】:
    public class IsNumericAttribute : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value != null)
            {
                decimal val;
                var isNumeric = decimal.TryParse(value.ToString(), out val);
    
                if (!isNumeric)
                {                   
                    return new ValidationResult("Must be numeric");                    
                }
            }
    
            return ValidationResult.Success;
        }
    }
    

    【讨论】:

      【解决方案5】:

      试试这个属性:

      public class NumericAttribute : ValidationAttribute, IClientValidatable {
      
          public override bool IsValid(object value) {
              return value.ToString().All(c => (c >= '0' && c <= '9') || c == '-' || c == ' ');
          }
      
      
          public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) {
              var rule = new ModelClientValidationRule
              {
                  ErrorMessage = FormatErrorMessage(metadata.DisplayName),
                  ValidationType = "numeric"
              };
              yield return rule;
          }
      }
      

      而且您还必须在验证器插件中注册该属性:

      if($.validator){
           $.validator.unobtrusive.adapters.add(
              'numeric', [], function (options) {
                  options.rules['numeric'] = options.params;
                  options.messages['numeric'] = options.message;
              }
          );
      }
      

      【讨论】:

        【解决方案6】:

        通过在我的视图模型中将属性设为字符串,我能够绕过所有框架消息。

        [Range(0, 15, ErrorMessage = "Can only be between 0 .. 15")]
        [StringLength(2, ErrorMessage = "Max 2 digits")]
        [Remote("PredictionOK", "Predict", ErrorMessage = "Prediction can only be a number in range 0 .. 15")]
        public string HomeTeamPrediction { get; set; }
        

        然后我需要在我的get方法中做一些转换:

        viewModel.HomeTeamPrediction = databaseModel.HomeTeamPrediction.ToString();
        

        和发布方法:

        databaseModel.HomeTeamPrediction = int.Parse(viewModel.HomeTeamPrediction);
        

        这在使用 range 属性时效果最好,否则需要一些额外的验证来确保该值是一个数字。

        您还可以通过将范围内的数字更改为正确的类型来指定数字的类型:

        [Range(0, 10000000F, ErrorMessageResourceType = typeof(GauErrorMessages), ErrorMessageResourceName = nameof(GauErrorMessages.MoneyRange))]
        

        【讨论】:

          【解决方案7】:

          差不多十年过去了,但这个问题在 Asp.Net Core 2.2 中仍然有效。

          我通过在输入字段中添加 data-val-number 来管理消息的使用本地化:

          <input asp-for="Age" data-val-number="@_localize["Please enter a valid number."]"/>
          

          【讨论】:

            【解决方案8】:

            ASP.NET Core 3.1

            这是我对该功能的实现,它适用于服务器端以及 jquery 验证不显眼的自定义错误消息,就像任何其他属性一样:

            属性:

              [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
                public class MustBeIntegerAttribute : ValidationAttribute, IClientModelValidator
                {
                    public void AddValidation(ClientModelValidationContext context)
                    {
                        MergeAttribute(context.Attributes, "data-val", "true");
                        var errorMsg = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
                        MergeAttribute(context.Attributes, "data-val-mustbeinteger", errorMsg);
                    }
            
                    public override bool IsValid(object value)
                    {
                        return int.TryParse(value?.ToString() ?? "", out int newVal);
                    }
            
                    private bool MergeAttribute(
                          IDictionary<string, string> attributes,
                          string key,
                          string value)
                    {
                        if (attributes.ContainsKey(key))
                        {
                            return false;
                        }
                        attributes.Add(key, value);
                        return true;
                    }
                }
            

            客户端逻辑:

            $.validator.addMethod("mustbeinteger",
                function (value, element, parameters) {
                    return !isNaN(parseInt(value)) && isFinite(value);
                });
            
            $.validator.unobtrusive.adapters.add("mustbeinteger", [], function (options) {
                options.rules.mustbeinteger = {};
                options.messages["mustbeinteger"] = options.message;
            });
            

            最后是用法:

             [MustBeInteger(ErrorMessage = "You must provide a valid number")]
             public int SomeNumber { get; set; }
            

            【讨论】:

              【解决方案9】:

              您可以编写自定义验证属性:

              [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
              public class Numeric : ValidationAttribute
              {
                  public Numeric(string errorMessage) : base(errorMessage)
                  {
                  }
              
                  /// <summary>
                  /// Check if given value is numeric
                  /// </summary>
                  /// <param name="value">The input value</param>
                  /// <returns>True if value is numeric</returns>
                  public override bool IsValid(object value)
                  {
                      return decimal.TryParse(value?.ToString(), out _);
                  }
              }
              

              然后,您可以在您的财产上使用以下注释:

              [Numeric("Please fill in a valid number.")]
              public int NumberOfBooks { get; set; }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2022-01-27
                • 1970-01-01
                • 1970-01-01
                • 2012-08-31
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多