0
votes

I'm using the jquery unobtrusive method of validating my models in the UI. I have a numeric field in a model that I want to validate as a number. Out of the box, it almost works correctly. It fails on the client side when validating .33 versus 0.33. I know that I can change regex in the jquery validation plugin, but that doesn't seem to be ideal.

So, to try to fix the issue without modding the plugin itself, I created the following validation attribute:

public class DecimalValidator : System.ComponentModel.DataAnnotations.ValidationAttribute, System.Web.Mvc.IClientValidatable
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        decimal val = 0;
        ValidationResult ret = new ValidationResult("Must be a valid decimal");

        if (decimal.TryParse(value.ToString(), out val) )
            return ValidationResult.Success;
        else
            return ret;
    }


    #region IClientValidatable Members

    public System.Collections.Generic.IEnumerable<System.Web.Mvc.ModelClientValidationRule> GetClientValidationRules(System.Web.Mvc.ModelMetadata metadata, System.Web.Mvc.ControllerContext context)
    {
        List<System.Web.Mvc.ModelClientValidationRule> ret = new List<System.Web.Mvc.ModelClientValidationRule>();

        System.Web.Mvc.ModelClientValidationRule validDecimalRule = new System.Web.Mvc.ModelClientValidationRule
        {
            ErrorMessage = "Please enter a valid decimal.",
            ValidationType = "decimal"
        };

        ret.Add(validDecimalRule);

        return ret;
    }

    #endregion
}

And applied it like so:

    /// <summary>
    /// The price per unit.
    /// </summary>
    [Range(0, double.MaxValue)]
    [Display(Name = "Price")]
    [DecimalValidator]
    public decimal UnitPrice { get; set; }

The problem is that the html still renders with data-val-number="The field Price must be a number." in addition to the new one, data-val-decimal="Please enter a valid decimal."

How do I keep the default validation attributes from being rendered?

3

3 Answers

0
votes

I believe the [Range(0, double.MaxValue)] is forcing it load the number validation. Try adding that into your custom validator and removing it from your field decorators.

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    decimal val = 0;
    ValidationResult ret = new ValidationResult("Must be a valid decimal");
    ValidationResult rangeRet = new ValidationResult(String.Format("Number must be between 0 and {0}", double.MaxValue.ToString());

    if (decimal.TryParse(value.ToString(), out val) )
        return ValidationResult.Success;
    else if (value < 0 || value > double.MaxValue)
        return rangeRet;
    else
        return ret;
}
0
votes

I found the answer to be to use $.extend to replace the number validation in the plugin with the regex that allows .33 and 0.33

-1
votes

Why are you creating a custom validator? MVC will validate for you by default. If you make your type nullable (decimal?) then MVC will set UnitPrice to null if a non-decimal is entered, as well as make your model state invalid if it violates any other validation you are doing.