tags:

views:

161

answers:

2

Hi, if anyone has much experience using [C#] FluentValidation and has any ideas for the below question any help would be much appreciated.

I have 2 Generic Lists (both with string datatype) - "Name" and "Url". They both have the same amount of items, thus indexed items match up i.e., Names[0] correlates with Urls[0].

The only problem I am having is with validating empty items in each list. The rules i need are:

if an item is empty in Name[2] then Url[2] should not be empty. if an item is empty in Url[2] then Name[2] should not be empty. if they are both empty then we do not want to validate, we want to ignore.

note: I have used the index 2 in the above example but it could be anything

So far I have:

RuleFor(f => f.Names).Must(d => d.All(s => !String.IsNullOrEmpty(s)))
                .WithMessage("Names cannot be empty.")

RuleFor(f => f.URLs).Must(urls => urls.All(s => !String.IsNullOrEmpty(s)))
                .WithMessage("URLs cannot be empty.")

This checks that no items are empty in either list, however I need to be able to not validate items for being empty in one list if the correlating item in the other is also empty (If both are empty then we just want to ignore it).

Any ideas?

+1  A: 

Here is some Pseudo-code of a brute force solution. (I cannot think of any LINQ way of doing indexed comparisions) Sorry for the butchering of Fluent syntax.

Must(Names.Length == URLs.Length).WithMessage("Names must be equal in size to URLs");
for (int i = 0; i < Name.Length; i++)
{
    Must(string.IsNullOrEmpty(Names[i]) ^^ string.IsNullOrEmpty(URLs[i])).WithMessage("Either Name and URL must be non-empty, or both must be empty, index = " + i);
}

Hopefully you get the gist of it, you may also want to look into general LINQ methods, there is likely one that I missed. Basically you are wanting to do a join, and then check for invalid results in the merged list, but again I am unsure how to do a row by row and not simply a many to many join.

Guvante
@Guvante: Thanks, your pseudo-code got the ball rolling in the right direction (see posted answer). +1 for you :)
Scozzard
+1  A: 

I ended up using the following FluentValidation code to check the corrosponding items in each list, big thanks to Guvante as it was inspired by his Pseudo-code :)

RuleFor(f => f.Names).Must((f, d) =>
            {
                for (int i = 0; i < d.Count; i++)
                {
                    if ((String.IsNullOrEmpty(d[i]) &&
                         !String.IsNullOrEmpty(f.URLs[i])))
                        return false;
                }

                return true;
            })
            .WithMessage("Names cannot be empty.");

            RuleFor(f => f.URLs).Must((f, u) =>
            {
                for (int i = 0; i < u.Count; i++)
                {
                    if ((String.IsNullOrEmpty(u[i]) &&
                         !String.IsNullOrEmpty(f.Names[i])))
                        return false;
                }

                return true;
            })
            .WithMessage("URLs cannot be empty.");
Scozzard