多个复选框的MVC 3自定义验证属性

时间:2012-02-29 00:07:00

标签: asp.net-mvc-3 forms validation custom-attributes

我正在使用自定义属性对冗长的表单进行验证。其中一个传入字段是一系列复选框,我用它来允许用户为相应的数据库字段设置多个值(我知道我可以使用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方法没有通过它们的属性名找到这些复选框。我在这里做错了什么?

2 个答案:

答案 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方法中进行验证。更容易,没有后期绑定。