2012-02-29 102 views
0

我正在使用自定义属性在冗长的表单上进行验证。其中一个传入字段是一系列复选框,我使用它来允许用户为相应的数据库字段设置多个值(我知道我可以使用MultiSelectList,但我不是他们的忠实粉丝)。然后,我将ActionResult的POST方法中的各种复选框值组装成一个字符串,然后将其加载到数据库中。这部分运作良好。MVC 3多个复选框的自定义验证属性

但是,我需要验证他们检查了至少一个复选框(即数据库值本身不能为空)。所以我写了一个自定义验证属性,查找每个复选框的存在,并且如果至少存在一个复选框,那么它将通过验证。这是我写的验证本身的代码:

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; 
    } 
} 

我打电话验证作为视图模型的属性:

[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; 

即使复选框被选中,也会解析为空。我进一步证实了检查值肯定存在于ActionResult的FormCollection中。就好像我的语法错了或者某些东西,比如GetProperty方法没有通过它们的属性名称找到这些复选框。我在这里做错了什么?

回答

4

更改视图模型是

[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上创建一个扩展。

编辑 - 从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 }); 
+0

解决@ ScubaSteve的有关客户端验证评论我不得不调整这一点(变“的ICollection ”到“串[]”,并确保视图模型传递作为POST ActionResult中的一个参数),但是你让我接触到最佳解决方案。它还帮助我通过将处理端转换为“foreach”循环来缩短我的“接收者”代码。谢谢,那太棒了! – Sylver 2012-02-29 14:10:55

+0

这适用于服务器端验证,但不会像通常那样自动添加客户端验证。 – ScubaSteve 2013-01-10 16:23:46

+0

@ScubaSteve有些事情需要留给问题的提问者去做。 – heads5150 2013-01-10 19:40:22

0

我不会使用这个属性,除非你想做客户端验证。相反,我只是让你的模型从IValidatableObject派生出来,然后在IsValid方法中进行验证。更容易,也没有迟到的约束。