Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,36 @@ List<ValidationResult> validationResults
);
}

public bool TryValidateObjectRecursive<T>(
T obj,
List<ValidationResult> validationResults,
IDictionary<object, object> validationContextItems = null
)
{
return TryValidateObjectRecursive(
obj,
validationResults,
new HashSet<object>(),
validationContextItems
);
}

private bool TryValidateObject(
object obj,
ICollection<ValidationResult> validationResults,
IDictionary<object, object> validationContextItems = null
)
)
{
return Validator.TryValidateObject(
obj,
new ValidationContext(
obj,
null,
validationContextItems
),
),
validationResults,
true
);
}

public bool TryValidateObjectRecursive<T>(
T obj,
List<ValidationResult> validationResults,
IDictionary<object, object> validationContextItems = null
)
{
return TryValidateObjectRecursive(
obj,
validationResults,
new HashSet<object>(),
validationContextItems
);
);
}

private bool TryValidateObjectRecursive<T>(
Expand Down Expand Up @@ -87,12 +87,15 @@ private bool TryValidateObjectRecursive<T>(
continue;

case IEnumerable asEnumerable:
foreach (var enumObj in asEnumerable)
foreach (var item in asEnumerable)
{
if (enumObj == null) continue;
//NOTE: This does not tell you which item in the IEnumerable<T> failed
//Possibly, should have a separate case for Array/Dictionary

if (item == null) continue;
nestedResults = new List<ValidationResult>();
if (!TryValidateObjectRecursive(
enumObj,
item,
nestedResults,
validatedObjects,
validationContextItems
Expand All @@ -107,7 +110,7 @@ private bool TryValidateObjectRecursive<T>(
validationResult.ErrorMessage,
validationResult.MemberNames.Select(x => property1.Name + '.' + x)
));
}
}
}
}
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using RecursiveDataAnnotationsValidation.Tests.TestModels;
using Xunit;

namespace RecursiveDataAnnotationsValidation.Tests
{
public class EnumerableExampleTests
{
private readonly IRecursiveDataAnnotationValidator _validator = new RecursiveDataAnnotationValidator();

[Fact]
public void Passes_all_validation_no_children()
{
var sut = new EnumerableExample
{
Name = "Passes all",
Age = 75,
Items = new List<ItemExample>()
};

var validationResults = new List<ValidationResult>();
var result = _validator.TryValidateObjectRecursive(sut, validationResults);

Assert.True(result);
Assert.Empty(validationResults);
}

[Fact]
public void Passes_all_validation_with_children()
{
var sut = new EnumerableExample
{
Name = "Passes all",
Age = 75,
Items = new List<ItemExample>
{
new ItemExample
{
Name = "Child 1",
SimpleA = new SimpleExample
{
IntegerA = 125,
StringB = "child-1-stringB",
BoolC = true,
ExampleEnumD = ExampleEnum.ValueC
}
},
new ItemExample
{
Name = "Child 2",
SimpleA = new SimpleExample
{
IntegerA = 15,
StringB = "child-2-string-abc",
BoolC = false,
ExampleEnumD = ExampleEnum.ValueA
}
}
}
};

var validationResults = new List<ValidationResult>();
var result = _validator.TryValidateObjectRecursive(sut, validationResults);

Assert.True(result);
Assert.Empty(validationResults);
}

[Fact]
public void Fails_on_Items_Child2_SimpleA_BoolC()
{
var sut = new EnumerableExample
{
Name = "Passes all",
Age = 75,
Items = new List<ItemExample>
{
new ItemExample
{
Name = "Child 1",
SimpleA = new SimpleExample
{
IntegerA = 125,
StringB = "child-1-stringB",
BoolC = true,
ExampleEnumD = ExampleEnum.ValueC
}
},
new ItemExample
{
Name = "Child 2",
SimpleA = new SimpleExample
{
IntegerA = 15,
StringB = "child-2-string-abc",
BoolC = null, // failure
ExampleEnumD = ExampleEnum.ValueA
}
}
}
};

var validationResults = new List<ValidationResult>();
var result = _validator.TryValidateObjectRecursive(sut, validationResults);

Assert.False(result);
Assert.NotEmpty(validationResults);
Assert.NotNull(validationResults
.FirstOrDefault(x => x.MemberNames.Contains("Items.SimpleA.BoolC")));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace RecursiveDataAnnotationsValidation.Tests.TestModels
{
public class EnumerableExample
{
[Required]
public string Name { get; set; }

[Required]
public int? Age { get; set; }

[Required]
public IEnumerable<ItemExample> Items { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;

namespace RecursiveDataAnnotationsValidation.Tests.TestModels
{
public class ItemExample
{
[Required]
public string Name { get; set; }

[Required]
public SimpleExample SimpleA { get; set; }
}
}