MVC DropDownListFor and StringLength Attribute Not Playing Well together
Asked Answered
P

3

5

My stringlength validation always fails on dropdownlists with a string value.

Here is my model:

[Required(ErrorMessage = "Required")]
[StringLength(2, MinimumLength = 2)]
[Display(Name = "Home Address State")]
public string HomeAddressState { get; set; }

Here is my view:

@Html.DropDownListFor(model => model.HomeAddressState, new SelectList(ViewBag.States, "Value", "Text"), string.Empty)
@Html.ValidationMessageFor(model => model.HomeAddressState)

Here is the html output:

<select data-val="true" data-val-length="The field Home Address State must be a string with a minimum length of 2 and a maximum length of 2." data-val-length-max="2" data-val-length-min="2" data-val-required="Required" id="HomeAddressState" name="HomeAddressState"><option value=""></option>
<option value="CA">California</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="OH">Ohio</option>
</select>

No matter what option is selected, the StringLength validation fails client-side. What am I doing incorrectly?

Prospect answered 10/7, 2012 at 16:20 Comment(3)
Why do you have need StringLength validation for a drop down list?Circumfluent
presumably because his data model validation is (correctly) independent from his client view.Excommunication
bhamlin is correct. I use [StringLength(2, MinimumLength = 2)] to correctly create the char(2) field in my database since I'm using code-first. I didn't want to go the fluent way.Prospect
E
6

Here's the relevant jquery-validation code. As you can see, it looks like it applies the length validation to the number of options selected, not the length of the option. Seems to only apply to multi-select listboxes. Kind of odd, to be honest.

maxlength: function(value, element, param) {
    return this.optional(element) || this.getLength($.trim(value), element) <= param;
}

getLength: function(value, element) {
    switch( element.nodeName.toLowerCase() ) {
        case 'select':
            return $("option:selected", element).length;
        case 'input':
            if( this.checkable( element) )
                return this.findByName(element.name).filter(':checked').length;
    }
    return value.length;
}

What you can do is override the getLength function yourself to just return value.length directly.

$.validator.prototype.getLength = function (value, element) {
    return value.length;
}
Excommunication answered 10/7, 2012 at 16:40 Comment(4)
Anywhere after you include the jquery validation library.Excommunication
That's what I thought, but no dice. The default behavior trumps my override. I wonder how the validation library is actually instantiated. It looks like it's a lazy load. In $(document).ready() I queried $.validator.methods.getLength and it's null.Prospect
My mistake, getLength isn't on the methods object. Try $.validator.prototype.getLengthExcommunication
Nice solution. I have set the code in $(document).ready(function () { ... }); and working fine. Thanks!Widower
E
2

To avoid breaking the logic for checkboxes and multiple selectboxes, you could use:

$.validator.prototype.getLength = function (value, element) {
    switch (element.nodeName.toLowerCase()) {
        case 'select':
            {
                var attr = $(this).attr('multiple');
                // For some browsers, `attr` is undefined; for others,
                // `attr` is false.  Check for both.
                if (typeof attr !== 'undefined' && attr !== false) {
                    return $("option:selected", element).length;
                }
            }
        case 'input':
            if (this.checkable(element))
                return this.findByName(element.name).filter(':checked').length;
    }
    return value.length;
}

WARNING: I tested this only on DropDownFor, so use at your own risk....

Examinee answered 19/10, 2012 at 14:9 Comment(0)
C
0

because StringLength match rangelength rule in jquery.validate. In the case of a select list it will check the number of items selected not the length of the value selected so if you write a rule of minimum length of 1 it will work

Cohbath answered 10/7, 2012 at 16:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.