How to Override Default Validation Error Message for Integer or Decimal Property in ASP.NET MVC – The value ‘xxx’ is not valid for Property

Unfortunately Microsoft did not incorporate a DataAnnotation to change the default message The value ‘xxx’ is not valid for Property to a custom one.

This is when you create an int or decimal property in your model, you bind it to an input box (TextBoxFor) then try to submit the form, then you get this ugly looking message. Below I show you how to change it to whatever you want.





First you create a class somewhere in your project. I usually have these type of helper classes in a Helpers folder.

For decimal property

namespace SomeNamespace
{
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
    public class ValidDecimal : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
            if (value == null || value.ToString().Length == 0) {
                return ValidationResult.Success;
            }
            decimal d;

            return !decimal.TryParse(value.ToString(), out d) ? new ValidationResult(ErrorMessage) : ValidationResult.Success;
        }
    }
}

public class ValidDecimalValidator : DataAnnotationsModelValidator<ValidDecimal>
{
    public ValidDecimalValidator(ModelMetadata metadata, ControllerContext context, ValidDecimal attribute)
        : base(metadata, context, attribute) {
        if (!attribute.IsValid(context.HttpContext.Request.Form[metadata.PropertyName])) {
            var propertyName = metadata.PropertyName;
            context.Controller.ViewData.ModelState[propertyName].Errors.Clear();
            context.Controller.ViewData.ModelState[propertyName].Errors.Add(attribute.ErrorMessage);
        }
    }
}

For integer property

namespace SomeNamespace
{
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
    public class ValidInteger : ValidationAttribute
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
            if (value == null || value.ToString().Length == 0) {
                return ValidationResult.Success;
            }
            int i;

            return !int.TryParse(value.ToString(), out i) ? new ValidationResult(ErrorMessage) : ValidationResult.Success;
        }
    }
}

public class ValidIntegerValidator : DataAnnotationsModelValidator<ValidInteger>
{
    public ValidIntegerValidator(ModelMetadata metadata, ControllerContext context, ValidInteger attribute)
        : base(metadata, context, attribute) {
        if (!attribute.IsValid(context.HttpContext.Request.Form[metadata.PropertyName])) {
            var propertyName = metadata.PropertyName;
            context.Controller.ViewData.ModelState[propertyName].Errors.Clear();
            context.Controller.ViewData.ModelState[propertyName].Errors.Add(attribute.ErrorMessage);
        }
    }
}

Then you have to register the adapter in Global.asax under Application_Start() method

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(ValidInteger), typeof(ValidIntegerValidator));
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(ValidDecimal), typeof(ValidDecimalValidator));

And finally decorate your property in your model with these attributes using your own custom error message

[ValidInteger(ErrorMessage = "Only numbers allowed")]
public int MinParticipants { get; set; }

[ValidDecimal(ErrorMessage = "Only decimal numbers allowed")]
public decimal CPEHours { get; set; }

A big thank you to wechel for coming up with this solution in StackOverflow





Esau Silva
Software Engineer at Region One ESC
Microsoft Full Stack Application Developer
If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed.
Share