I'm wrote a custom ValidationAttribute that also implements IClientValidatable so that I can perform client-side validation using the Jquery.Unobtrusive library.
The issue I have is that even though I have multiple items in the EditLeadViewMode.AssociatedUsers collection, the GetClientValidationRules method only fires once, for the first item in the collectio and only the first item on the form is validated on the client. I can't figure out why it won't fire/validate for all of the items in my collection.
Sample HTML from the form. You can see that the data-val-requiredassignedto attribute is not set on the second box
<select id="AssociatedUsers[1].UserId" name="AssociatedUsers[1].UserId" class="form-control valid" data-val-requiredassignedto="ErrorMessage" aria-describedby="AssociatedUsers[1].UserId-error" aria-invalid="false"><option value="">-- Assign To --</option>
<option selected="selected" value="2">A.Carlie Predovic</option>
<option value="4">A.Earline Pfeffer</option>
<option value="10">F.Dorris Dare</option>
<option value="7">I.Alexandrea Hane</option>
<option value="8">I.Alexandrea Rogahn</option>
<option value="6">I.Heber Greenfelder</option>
<option value="9">I.Maeve Koepp</option>
</select>
<select id="AssociatedUsers[2].UserId" name="AssociatedUsers[2].UserId" class="form-control" ><option value="">-- Assign To --</option>
<option value="2">A.Carlie Predovic</option>
<option value="4">A.Earline Pfeffer</option>
<option value="5">A.Jarrod Breitenberg</option>
<option selected="selected" value="3">A.Sheridan Maggio</option>
<option value="10">F.Dorris Dare</option>
</select>
ViewModel bound to the view
public sealed class EditLeadViewModel : IHelperSetup
{
public EditLeadViewModel()
{
}
public IEnumerable<UserInLeadRole> AssociatedUsers { get; set; }
}
public class UserInLeadRole
{
[AssignToUserValidationAttribute]
public int? UserId { get; set; }
}
Custom Attribute
public class AssignToUserValidationAttribute : ValidationAttribute, IClientValidatable
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
//Server side validation here
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
return new List<ModelClientValidationRule>
{
new ModelClientValidationRule{
ValidationType = "requiredassignedto",
ErrorMessage = "This field is required"
}
};
}
}
Javascript for wiring up my custom unobtrusive adapter
function addRule(name, params, ruleFn)
{
$.validator.addMethod(name, ruleFn);
$.validator.unobtrusive.adapters.add(name, params,
function (options)
{
options.rules[name] = options.params;
options.messages[name] = options.message;
});
}
addRule("requiredassignedto",[],
function (value, el, params) {
///Client side validation logic here
});
})(jQuery);
I can't find any documentation saying that a custom validator will only fire once on a collection, but I'm obviously missing something.