我正在使用自定义属性对冗长的表单进行验证。其中一个传入字段是一系列复选框,我用它来允许用户为相应的数据库字段设置多个值(我知道我可以使用MultiSelectList,但我不是他们的忠实粉丝)。然后我将ActionResult的POST方法中的各种复选框值组装成单个字符串,然后再将其加载到数据库中。那部分效果很好。
但是,我需要验证他们已经检查了至少一个复选框(即数据库值本身不能为空)。所以我编写了一个自定义验证属性,用于查找每个复选框的存在,如果至少存在一个复选框,则它会通过验证。这是我为验证本身编写的代码:
public class ConfirmLAAttribute : ValidationAttribute
{
public ConfirmLAAttribute()
{
}
protected override ValidationResult IsValid(Object value, ValidationContext validationContext)
{
string lAppTest = String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAAccent") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAShade") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAArticulation") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAMassing") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAScreening") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LARock") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAEdging") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAWindbreak") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAGroundcover") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LANaturalizing") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAOrchard") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LATopiary") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAHerb") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LAContainer") != null) ? "X" : String.Empty;
lAppTest += (validationContext.ObjectType.GetProperty("LABog") != null) ? "X" : String.Empty;
if (String.IsNullOrEmpty(lAppTest)) {
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
return ValidationResult.Success;
}
}
我将验证作为View Model的一个属性调用:
[ConfirmLA(ErrorMessage = "You must select at least one Landscape Application!")]
public string Landscape_Application { get; set; }
视图模型中的HTML代码只是重复:
<input type="checkbox" name="LAAccent" value="true" /> Accent/Feature<br />
表格内部(即这15次,每个复选框一次)。
问题是这总是抛出错误。我在验证代码本身内部进行了调试,并且没有通过其属性名称识别任何复选框。换句话说,每一个:
lAppTest += (validationContext.ObjectType.GetProperty("LAAccent") != null) ? "X" : String.Empty;
即使选中了复选框,也会解析为null。我进一步确认检查的值肯定存在于ActionResult的FormCollection中。这就好像我的语法错误或者某些东西,比如GetProperty方法没有通过它们的属性名找到这些复选框。我在这里做错了什么?
答案 0 :(得分:4)
将您的View模型更改为
[Required(ErrorMessage = "You must select at least one Landscape Application!")]
public ICollection<string> LandscapeServices { get; set; }
将您的Html更改为
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAAccent" /> Accent/Feature<br />
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAShade" /> Accent/Feature<br />
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAArticulation" /> Accent/Feature<br />
/*etc etc*/
当您点击提交时,所有选定的值都将添加到属性LandscapeServices。
请注意,这仅适用于服务器端验证。如果您想要客户端验证,则必须使用您自己的javascript验证函数在Required上创建扩展。
编辑 - 解决@ ScubaSteve关于SO answer的客户端验证的评论
$(function(){
$.validator.addMethod('required_group', function(value, element) {
var $module = $(element).parents('form');
return $module.find('input.checkbox:checked').length;
}, 'Select at least one Service please');
$.validator.addClassRules('required-checkbox', { 'required_group' : true });
答案 1 :(得分:0)
除非您想进行客户端验证,否则我不会使用此属性。相反,我只是让你的模型从IValidatableObject派生,并在IsValid方法中进行验证。更容易,没有后期绑定。