still got no solution for my situation. i want to validate checkboxes by ValidationAttribute, IClientValidatable.
my GetClientValidationRules() function is not getting called because i impose my custom attribute on a list type property in view model.
[AtleastOne(ErrorMessage = "Select at least one checkbox.")]
public List<Hobby> Hobbies { get; set; }
if i impose AtleastOne attrbute on a property which does not return list then GetClientValidationRules() function is calling.
anyone can tell me what is the reason for which GetClientValidationRules() function is not calling when working with list type property.
please some one help me with right direction. thanks
EDIT
see my model and view model code
public class Product
{
public int ID { set; get; }
public string Name { set; get; }
}
public class Hobby
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class SampleViewModel
{
[Display(Name = "Products")]
public List<Product> Products { set; get; }
[AtleastOne(ErrorMessage = "Select at least one checkbox.")]
public List<Hobby> Hobbies { get; set; }
[Required(ErrorMessage = "Select any Product")]
public int SelectedProductId { set; get; }
[Required(ErrorMessage = "Select Male or Female")]
public string Gender { get; set; }
}
custom validation code
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class AtleastOneAttribute : ValidationAttribute, IClientValidatable
{
// For Server side
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
var oHobby=value as IEnumerable;
foreach (var _object in oHobby)
{
Hobby _oHobby = (Hobby)_object;
if (_oHobby.IsSelected)
{
return ValidationResult.Success;
}
}
}
return new ValidationResult(ErrorMessage);
}
// Implement IClientValidatable for client side Validation
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "atleastonetrue",
};
yield return rule;
}
}
See how i am generating checkboxes in loop
<div class="col-md-offset-2 col-md-10">
<b>Hobbies</b><br />
@for (int x = 0; x < Model.Hobbies.Count(); x++)
{
@Html.CheckBoxFor(p => p.Hobbies[x].IsSelected, new { @class = "hobbycls" }) @:
@Html.LabelFor(p => p.Hobbies[x].IsSelected, Model.Hobbies[x].Name) @:
@Html.HiddenFor(p => p.Hobbies[x].Name)
}
@Html.ValidationMessageFor(model => model.Hobbies)
</div>
client side code
$(function () {
$.validator.unobtrusive.adapters.add('atleastonetrue', [], function (options) {
options.rules['restrictbackdates'] = { mindate: options.params.mindate };
options.messages['atleastonetrue'] = options.message;
options.rules['atleastonetrue'] = options.params;
alert('hello');
alert(options.message);
});
$.validator.addMethod("atleastonetrue", function (value, element, param) {
return $('.hobbycls:checked').size() > 0;
});
});
see the html for checkboxes
<div class="col-md-offset-2 col-md-10">
<b>Hobbies</b><br>
<input type="checkbox" value="true" name="Hobbies[0].IsSelected" id="Hobbies_0__IsSelected" data-val-required="Please check at least one box" data-val="true" class="hobbycls input-validation-error"><input type="hidden" value="false" name="Hobbies[0].IsSelected">
<label for="Hobbies_0__IsSelected">Reading</label>
<input type="hidden" value="Reading" name="Hobbies[0].Name" id="Hobbies_0__Name"><input type="checkbox" value="true" name="Hobbies[1].IsSelected" id="Hobbies_1__IsSelected" data-val-required="Please check at least one box" data-val="true" class="hobbycls input-validation-error"><input type="hidden" value="false" name="Hobbies[1].IsSelected">
<label for="Hobbies_1__IsSelected">Sports</label>
<input type="hidden" value="Sports" name="Hobbies[1].Name" id="Hobbies_1__Name"><input type="checkbox" value="true" name="Hobbies[2].IsSelected" id="Hobbies_2__IsSelected" data-val-required="Please check at least one box" data-val="true" class="hobbycls input-validation-error"><input type="hidden" value="false" name="Hobbies[2].IsSelected">
<label for="Hobbies_2__IsSelected">Movies</label>
<input type="hidden" value="Movies" name="Hobbies[2].Name" id="Hobbies_2__Name"> <span data-valmsg-replace="true" data-valmsg-for="Hobbies" class="field-validation-valid"></span>
</div>
1) the main problem is my client side js code is not firing 2) when i debug then notice this function GetClientValidationRules is not getting called because i use custom attribute on a property which return list type. here it is.
[AtleastOne(ErrorMessage = "Select at least one checkbox.")]
public List<Hobby> Hobbies { get; set; }
so please see my code and tell me what is wrong in it ? thanks