[asp.net-mvc] Int or Number DataType for DataAnnotation validation attribute

On my MVC3 project, I store score prediction for football/soccer/hockey/... sport game. So one of properties of my prediction class looks like this:

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

Now, I need also change error message for a data type, int in my case. There is some default one used - "The field HomeTeamPrediction must be a number.". Need to find a way how to change this error message. This validation message also seem to take prediction for Remote validation one.

I've tried [DataType] attribute but this does not seem to be plain number in system.componentmodel.dataannotations.datatype enumeration.

This question is related to asp.net-mvc asp.net-mvc-3 data-annotations

The answer is


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

For any number validation you have to use different different range validation as per your requirements :

For Integer

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

for float

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

for double

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

Use regex in data annotation

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

I was able to bypass all the framework messages by making the property a string in my view model.

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

Then I need to do some conversion in my get method:

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

and post method:

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

This works best when using the range attribute, otherwise some additional validation would be needed to make sure the value is a number.

You can also specify the type of number by changing the numbers in the range to the correct type:

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

Try this attribute :

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

And also you must register the attribute in the validator plugin:

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

ASP.NET Core 3.1

This is my implementation of the feature, it works on server side as well as with jquery validation unobtrusive with a custom error message just like any other attribute:

The attribute:

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

Client side logic:

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

And finally the Usage:

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

Try one of these regular expressions:

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


// for numbers that begin from 1
[RegularExpression("([1-9][0-9]*)")] 

hope it helps :D


almost a decade passed but the issue still valid with Asp.Net Core 2.2 as well.

I managed it by adding data-val-number to the input field the use localization on the message:

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

You can write a custom validation attribute:

[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 _);
    }
}

On your property you can then use the following annotation:

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

Examples related to asp.net-mvc

Using Lato fonts in my css (@font-face) Better solution without exluding fields from Binding Vue.js get selected option on @change You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to send json data in POST request using C# VS 2017 Metadata file '.dll could not be found The default XML namespace of the project must be the MSBuild XML namespace How to create roles in ASP.NET Core and assign them to users? The model item passed into the dictionary is of type .. but this dictionary requires a model item of type How to use npm with ASP.NET Core

Examples related to asp.net-mvc-3

Better solution without exluding fields from Binding IIs Error: Application Codebehind=“Global.asax.cs” Inherits=“nadeem.MvcApplication” Can we pass model as a parameter in RedirectToAction? return error message with actionResult Why is this error, 'Sequence contains no elements', happening? Failed to load resource: the server responded with a status of 500 (Internal Server Error) in Bind function 500.19 - Internal Server Error - The requested page cannot be accessed because the related configuration data for the page is invalid String MinLength and MaxLength validation don't work (asp.net mvc) How to set the value of a hidden field from a controller in mvc How to set a CheckBox by default Checked in ASP.Net MVC

Examples related to data-annotations

How to add "required" attribute to mvc razor viewmodel text input editor ASP.NET MVC: Custom Validation by DataAnnotation Entity Framework code first unique column Why can't I reference System.ComponentModel.DataAnnotations? DataAnnotations validation (Regular Expression) in asp.net mvc 4 - razor view How do I specify the columns and rows of a multiline Editor-For in ASP.MVC? Disable Required validation attribute under certain circumstances Assign format of DateTime with data annotations? displayname attribute vs display attribute Int or Number DataType for DataAnnotation validation attribute