title: Client-side custom annotation validation not working
body: <p>I am trying to get client-side validation working with custom annotations in an ASP.NET MVC app.  Sorry for the somewhat lengthy post.</p>
  
  <p>Here is the custom attribute:</p>
  
  <pre><code>public class CustomStringLengthAttribute : ValidationAttribute, IClientValidatable
  {
      public int MaxLength { get; private set; }
      public int MinLength { get; set; }
  
      public CustomStringLengthAttribute(int maxLength)
          : base(GetDefaultErrorMessage)
      {
          MaxLength = maxLength;
      }
  
      private static string GetDefaultErrorMessage()
      {
          return "Max length {1}";
      }
  
      public override string FormatErrorMessage(string name)
      {
          return string.Format(ErrorMessageString, name, MaxLength, MinLength);
      }
  
      protected override ValidationResult IsValid(object value, ValidationContext validationContext)
      {
          ...
  
          if (length &gt; MaxLength || length &lt; MinLength)
              return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
  
          return ValidationResult.Success;
      }
  
      public IEnumerable&lt;ModelClientValidationRule&gt; GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
      {
          var rule = new ModelClientValidationRule();
          rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
          rule.ValidationType = "customstringlength";
          rule.ValidationParameters.Add("max", MaxLength);
          rule.ValidationParameters.Add("min", MinLength);
  
          yield return rule;
      }
  }
  </code></pre>
  
  <p>I use the attribute in my view model:</p>
  
  <pre><code>[CustomStringLength(25)]
  public virtual string BillAddress1 { get; set; }
  </code></pre>
  
  <p>The data- attributes appear to be generated as they should:</p>
  
  <pre><code>&lt;input data-val="true" data-val-customstringlength="Max length 25" data-val-customstringlength-max="25" data-val-customstringlength-min="0" id="BillAddress1" name="BillAddress1" type="text" value=""&gt;
  </code></pre>
  
  <p>The client-side validation kicks in, but I get "Uncaught TypeError: Cannot read property 'call' of undefined" in jquery.validate.js </p>
  
  <p>This is from "check: function(element) ..." in jquery.validate.js - the method variable is "undefined":</p>
  
  <p><img src="https://i.stack.imgur.com/rI3i2.jpg" alt="jquery.validate.js, check: function(element) ..."></p>
  
  <p>Looking at the rules variable explains why the method variable is undefined - for some reason the array containing the min and max parameters is "undefined" instead of being named "customstringlength":</p>
  
  <p><img src="https://i.stack.imgur.com/znOQc.jpg" alt="jquery.validate.js, check: function(element) ..."></p>
  
  <p>But why is it "undefined"??</p>
  
  <p>Here is my customValidation.js, where I add the adapter, etc:</p>
  
  <pre><code>(function ($) {
      if ($.validator &amp;&amp; $.validator.unobtrusive) {
  
          $.validator.unobtrusive.adapters.addMinMax("customstringlength", "min", "max");
  
          $.validator.addMethod("customstringlength", function (value, element, min, max) {
              if (value) {
                  if (value.length &lt; min || value.length &gt; max) {
                      return false;
                  }
              }
              return true;
          });
      }
  }(jQuery));
  </code></pre>
  
  <p>Here is where I invoke the validation for the form:</p>
  
  <pre><code>function validateForm(form) {
      prepareValidationScripts(form);
      var validator = $.data(form[0], 'validator');
      return validator.form();
  }
  
  function prepareValidationScripts(form) {
      if (form.executed)
          return;
      form.removeData("validator");
      $.validator.unobtrusive.parse(document);
      form.executed = true;
  }
  </code></pre>
  
  <p>I have been staring at this for too long - what am I missing??</p>