一个ASP.NET MVC验证器,用于确保至少选中一个复选框

时间:2010-12-20 16:18:27

标签: asp.net-mvc validation asp.net-mvc-2 dto

我有一个ASP.NET MVC 2项目,我在其中创建了一个数据传输对象,用于从网页表单接收数据。表单上有两组复选框。我想验证对象以确保每个组中至少有一个复选框被选中。

我正在服务器端进行验证,以便用户无法破解任何客户端验证。 (稍后我将使用jQuery添加客户端验证;这很简单。)

我的理解是我必须为我的数据传输对象类创建自己的自定义ValidationAttribute,但我不明白如何创建和使用一个可以接受任意复选框属性列表以确保至少有一个他们是真的。我猜我必须调用这样的属性:

[AtLeastOneCheckbox("set1check1", "set1check2", "set1check3",
    ErrorMessage = "You must check at least one checkbox in set 1.")]
[AtLeastOneCheckbox("set2check1", "set2check2", "set2check3", "set2check4", "set2check5",
    ErrorMessage = "You must check at least one checkbox in set 2.")]
public class MyFormDTO
{
    ...
}

AtLeastOneCheckboxAttribute的实现是什么样的?

或者我应该采用不同的方式进行此类验证吗?

2 个答案:

答案 0 :(得分:5)

如果您有多个复选框组,则只需要多次定义该属性。

[AttributeUsage( AttributeTargets.Class)]
public class AtLeastOneCheckboxAttribute : ValidationAttribute
{
    private string[] _checkboxNames;

    public AtLeastOneCheckboxAttribute(params string[] checkboxNames)
    {
        _checkboxNames = checkboxNames;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var propertyInfos = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Where(x=>_checkboxNames.Contains(x.Name));

        var values = propertyInfos.Select(x => x.GetGetMethod().Invoke(value, null));
        if (values.Any(x => Convert.ToBoolean(x)))
            return ValidationResult.Success;
        else
        {
            ErrorMessage = "At least one checkbox must be selected";
            return new ValidationResult(ErrorMessage);
        }
    }
}

<强>更新

如您所知,只有在所有属性都通过后才会调用类级别验证。为了得到错误,只使用空字符串作为键

答案 1 :(得分:0)

你的DTO,我猜你的ViewModel可能会出现IDataErrorInfo。 然后你可以像这样进行验证(注意我没有编译)

//I'm guessing you have a list of checkboxes
IEnumerable<bool> checkBoxes1;
IEnumerable<bool> checkBoxes2;

public class MyFormDTO : IDataErrorInfo
{
    public string this[string prop]
    {
        get
        {
            if(prop == "checkBoxes1")
            {
                if(checkBoxes1.Any(x => x == true))
                {
                    return "Error: You need to select atleast one checkbox from set1";
                }
            }
            else if(prop == "checkBoxes2")
            {
                if(checkBoxes2.Any(x => x == true))
                {
                    return "Error: You need to select atleast one checkbox from set2";
                }
            }
            return null;
        }
    }
    public string Error { get { return null; } }
}