1

I have a custom server side validator that works but I am struggling to get the client side working. Here is what I have so far.

The Validator is checking that one value entered is at least a percentage of another value entered.

public sealed class PercentageOfAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string sourcePropertyName;
    private readonly int minimumPercentage;

    public PercentageOfAttribute(string sourcePropertyName, int minimumPercentage)
    {
        this.sourcePropertyName = sourcePropertyName;
        this.minimumPercentage = minimumPercentage;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var propertyName = validationContext.ObjectType.GetProperty(this.sourcePropertyName);
        if (propertyName == null)
            return new ValidationResult(String.Format("Uknown property {0}", this.sourcePropertyName));

        int propertyValue = (int)propertyName.GetValue(validationContext.ObjectInstance, null);

        var minValue = (propertyValue / 100) * this.minimumPercentage;
        if ((int)value > minValue)
            return ValidationResult.Success;

        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));

    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = this.ErrorMessageString,
            ValidationType = "percentageof"
        };
        rule.ValidationParameters["propertyname"] = this.sourcePropertyName;
        rule.ValidationParameters["minimumpercentage"] = this.minimumPercentage;
        yield return rule;
    }
}

And the javascript for the client side...

jQuery.validator.addMethod("percentageof", function (value, element, params) {
    var propertyname = params['propertyname'];
    var minimumpercentage = param['minimumpercentage'];
    var propValue = $('#' + propertyname).val();
    var minValue = (propValue / 100) * minimumpercentage;
    if (value >= minValue) {
        return true;
    }
    return false;
});
jQuery.validator.unobtrusive.adapters.add("percentageof", ["propertyname", "minimumpercentage"], function (options) {
    options.rules['propertyname'] = options.params.propertyname;
    options.rules['minimumpercentage'] = options.params.minimumpercentage;
    options.message['percentageof'] = options.message;
});

I have debugged the addapters.add function and this is passing in the correct data. The "data-val-percentageof-*" values appear in the html and have the correct values.

The javascript error I am currently getting is "$.validator.methods[method] is undefined". I think this means that I have not correctly set up the client side validator. I've read through countless examples and tutorials but can't seem to figure out a combination that works.

If I remove all my custom stuff then the default client side validation works perfectly.

Can any one help show me what I am doing wrong?

EDIT:

The rendered html is as follows

<div class="form-group">
<label class="col-sm-3 control-label" for="PurchasePrice">Purchase Price (£36,000 minimum) *</label>
<div class="col-sm-6">
    <input id="PurchasePrice" class="form-control valid" type="text" value="0" name="PurchasePrice" data-val-required="Please enter a Purchase Price" data-val-range-min="36000" data-val-range-max="2147483647" data-val-range="Please enter at least £36,000" data-val-number="The field Purchase Price (£36,000 minimum) * must be a number." data-val="true">
    <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="PurchasePrice"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label" for="Deposit">Available Deposit (30% minimum)*</label>
<div class="col-sm-6">
    <input id="Deposit" class="form-control" type="text" value="0" name="Deposit" data-val-required="Please enter an Available Deposit" data-val-percentageof-propertyname="PurchasePrice" data-val-percentageof-minimumpercentage="30" data-val-percentageof="Please enter value that is at least 30% of the purchase price" data-val-number="The field Available Deposit (30% minimum)* must be a number." data-val="true">
    <span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="Deposit"></span>
</div>
</div>
2
  • Since this is likely a JavaScript issue, showing the relevant rendered HTML markup for the form as seen by the browser would be helpful. Commented Feb 19, 2014 at 15:48
  • Thanks for the reply - I've added the HTML in the edit above. Commented Feb 19, 2014 at 17:13

1 Answer 1

1

I managed to get this working by changing the format of the ...adapters.add function as follows

jQuery.validator.addMethod("percentageof", function (value, element, params) {
  var propertyname = params['propertyname'];
  var minimumpercentage = params['minimumpercentage'];
  var propValue = $('#' + propertyname).val();
  var minValue = (propValue / 100) * minimumpercentage;
  if (value >= minValue) {
    return true;
  }
  return false;
});
jQuery.validator.unobtrusive.adapters.add("percentageof", ["propertyname", "minimumpercentage"], function (options) {
  options.rules["percentageof"] = options.params;
  if (options.message) {
    options.messages['percentageof'] = options.message;
  }
});

I was incorrectly trying to add the paramaters as rules!! There was also a typo in the addMethod section of code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.