简体   繁体   中英

MVC Model Validation Unobtrusive

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?

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

我发现答案是使用$ .extend用允许.33和0.33的正则表达式替换插件中的数字验证

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM