Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate directly against a List<T>?

I have a model class:

public class MyModel() { //properties here... }

And I want to validate a list of MyModel objects. So I created this validator:

class MyModelListValidator : AbstractValidator<List<MyModel>>
{
    public MyModelListValidator ()
    {
        RuleFor(x => x)
            .SetCollectionValidator(new MyModelValidator())
            .When(x => x != null);
    }

    private class MyModelValidator : AbstractValidator<MyModel>
    {
        public MyModelValidator()
        {
            //MyModel property validation here...
        }
    }
}

But the above doesn't work. An alternative is to create a class like:

public class MyModelList()
{
    public List<MyModel> Items { get; set; }
}

This would work.

But is there a way to do this without using this additional class?

like image 674
Ivan-Mark Debono Avatar asked Sep 02 '16 09:09

Ivan-Mark Debono


People also ask

How do I add data validation to a list?

Just go to the Data tab of the Ribbon, click on Data Validation, in the "Allow" drop down, choose "List". Then in the "Source" box, type your entries and click OK.

How do you check if a list is against another list?

1. In the formula, A2 is the first cell of the list you want to check if against to another one, C2:C6 is the second list you want to check based on. 2. You also can apply this formula =IF (COUNTIF ($C$2:$C$6,A2)>0,TRUE,FALSE) to handle this job.

How do I name a dropdown list in data validation?

In these examples, the table name is "AllMonths" and the column header for the list I want to use for my Data Validation dropdown list is "Months".) If your list is in a table, in the "Source" box of Data Validation, use the INDIRECT function to name the table and column header.

Why can't validator perform a validation against a thing object?

We cannot expect Validator to perform a validation against Thing objects which are stored in those properties, because it doesn't have any information about how it should validate those properties.


1 Answers

If you are using Data Annotations to perform validation you might need a custom attribute:

public class EnsureOneElementAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list != null)
        {
            return list.Count > 0;
        }
        return false;
    }
}

and then:

[EnsureOneElement(ErrorMessage = "At least a person is required")]
public List<Person> Persons { get; private set; }
or to make it more generic:

public class EnsureMinimumElementsAttribute : ValidationAttribute
{
    private readonly int _minElements;
    public EnsureMinimumElementsAttribute(int minElements)
    {
        _minElements = minElements;
    }

    public override bool IsValid(object value)
    {
        var list = value as IList;
        if (list != null)
        {
            return list.Count >= _minElements;
        }
        return false;
    }
}

and then:

[EnsureMinimumElements(1, ErrorMessage = "At least a person is required")]
public List<Person> Persons { get; private set; }
Personally I use FluentValidation.NET instead of Data Annotations to perform validation because I prefer the imperative validation logic instead of the declarative. I think it is more powerful. So my validation rule would simply look like this:

RuleFor(x => x.Persons)
    .Must(x => x.Count > 0)
    .WithMessage("At least a person is required");
like image 149
Melih Yilman Avatar answered Sep 29 '22 10:09

Melih Yilman