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

发布于 2024-10-08 08:01:49 字数 701 浏览 3 评论 0原文

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

我在服务器端进行验证,以便用户无法绕过任何客户端验证。 (稍后我将使用 jQuery 添加客户端验证;这很容易。)

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

[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 的实现会是什么样子?

或者我应该有不同的方式来进行这种验证?

I have an ASP.NET MVC 2 project in which I've created a data transfer object to receive data from a web page form. The form has two groups of checkboxes on it. I want to validate the object to make sure that at least one of the checkboxes in each group is checked.

I'm doing the validation on the server side so that a user won't be able to hack around any client-side validation. (I will add client-side validation with jQuery later; that's easy.)

My understanding is that I have to create my own custom ValidationAttribute for my data transfer object class, but I don't understand how to create and use one that can accept an arbitrary list of checkbox properties to make sure that at least one of them is true. I am guessing I will have to call the attributes like this:

[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
{
    ...
}

What would the implementation of AtLeastOneCheckboxAttribute look like?

Or is there a different way that I should do this kind of validation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

z祗昰~ 2024-10-15 08:01:49

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

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

更新

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

if you have several checkbox groups, you just need to deine the attribute several times.

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

UPDATE

as you have found out, class-level validation is called only after all properties pass. In order to get the error, just use empty string as the key.

甜点 2024-10-15 08:01:49

你的DTO,我猜你的ViewModel可以ihert 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; } }
}

Your DTO, which is I'm guessing your ViewModel can ihert IDataErrorInfo.
Then you can do your validation like this (note I didn't compile this)

//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; } }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文