Skip to content

Commit 8383994

Browse files
committed
Merge branch 'feature/#95' into develop
2 parents ccfd346 + 7e9eb55 commit 8383994

File tree

14 files changed

+127
-74
lines changed

14 files changed

+127
-74
lines changed

src/Simplify.Web.Tests/Model/Validation/ValidationAttributesExecutorTests.cs

+26-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
using Simplify.Web.Model.Validation;
55
using Simplify.Web.Tests.Model.Validation.Attributes;
66
using Simplify.Web.Tests.TestEntities;
7-
using Simplify.Web.Tests.TestEntities.HierarchyValidation;
7+
using Simplify.Web.Tests.TestEntities.Inheritance;
8+
using Simplify.Web.Tests.TestEntities.Nesting;
89

910
namespace Simplify.Web.Tests.Model.Validation
1011
{
@@ -35,17 +36,16 @@ public void Validate_ModelWithOnePropertyAndOneValidateAttribute_AttributeValida
3536
}
3637

3738
[Test]
38-
public void Validate_HierarchicalModel_NestedNullAttributeException()
39+
public void Validate_NestedProperties_NestedNullAttributeException()
3940
{
4041
// Arrange
41-
var model = new RootModel
42+
var model = new NestingRootModel
4243
{
43-
//BuiltInType = "test",
44-
CustomType = new ChildModel
44+
NestedProperty = new NestedModel
4545
{
46-
//BuiltInType = "test",
47-
CustomType = new SubChildModel()
48-
}
46+
NestedProperty = new SubNestedModel()
47+
},
48+
TestInt = 1
4949
};
5050

5151
// Act
@@ -54,7 +54,24 @@ public void Validate_HierarchicalModel_NestedNullAttributeException()
5454

5555
// Assert
5656
Assert.That(ex.Message,
57-
Does.StartWith($"Required property '{nameof(SubChildModel.BuiltInType)}' is null or empty"));
57+
Does.StartWith($"Required property '{nameof(SubNestedModel.BuiltInType)}' is null or empty"));
58+
}
59+
60+
[Test]
61+
public void Validate_InheritedProperty_NestedNullAttributeException()
62+
{
63+
// Arrange
64+
var model = new InheritanceRootModel
65+
{
66+
NestedProperty = new BaseNestedModel()
67+
};
68+
69+
// Act
70+
var ex = Assert.Throws<ModelValidationException>(() => _validator.Validate(model, null));
71+
72+
// Assert
73+
Assert.That(ex.Message,
74+
Does.StartWith($"Required property '{nameof(BaseNestedModel.BuiltInType)}' is null or empty"));
5875
}
5976
}
6077
}

src/Simplify.Web.Tests/TestEntities/HierarchyValidation/BaseModel.cs

-9
This file was deleted.

src/Simplify.Web.Tests/TestEntities/HierarchyValidation/ChildModel.cs

-12
This file was deleted.

src/Simplify.Web.Tests/TestEntities/HierarchyValidation/RootModel.cs

-14
This file was deleted.

src/Simplify.Web.Tests/TestEntities/HierarchyValidation/SubChildModel.cs

-12
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Simplify.Web.Model.Validation.Attributes;
2+
3+
#nullable disable
4+
5+
namespace Simplify.Web.Tests.TestEntities.Inheritance
6+
{
7+
public class BaseModel
8+
{
9+
[Required]
10+
public BaseNestedModel NestedProperty { get; set; }
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Simplify.Web.Model.Validation.Attributes;
2+
3+
#nullable disable
4+
5+
namespace Simplify.Web.Tests.TestEntities.Inheritance
6+
{
7+
public class BaseNestedModel
8+
{
9+
[Required]
10+
public string BuiltInType { get; set; }
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#nullable disable
2+
3+
namespace Simplify.Web.Tests.TestEntities.Inheritance
4+
{
5+
public class InheritanceRootModel : BaseModel
6+
{
7+
}
8+
}

src/Simplify.Web.Tests/TestEntities/HierarchyValidation/ISubChildModel.cs renamed to src/Simplify.Web.Tests/TestEntities/Nesting/ISubNestedModel.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using Simplify.Web.Model.Validation.Attributes;
22

3-
namespace Simplify.Web.Tests.TestEntities.HierarchyValidation
3+
namespace Simplify.Web.Tests.TestEntities.Nesting
44
{
5-
public interface ISubChildModel
5+
public interface ISubNestedModel
66
{
77
[Required]
88
string BuiltInType { get; set; }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#nullable disable
2+
3+
using Simplify.Web.Model.Validation.Attributes;
4+
5+
namespace Simplify.Web.Tests.TestEntities.Nesting
6+
{
7+
public class NestedModel
8+
{
9+
[Required]
10+
public ISubNestedModel NestedProperty { get; set; }
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#nullable disable
2+
3+
using Simplify.Web.Model.Validation.Attributes;
4+
5+
namespace Simplify.Web.Tests.TestEntities.Nesting
6+
{
7+
public class NestingRootModel
8+
{
9+
public NestedModel NestedProperty { get; set; }
10+
11+
[Required]
12+
public int? TestInt { get; set; }
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#nullable disable
2+
3+
namespace Simplify.Web.Tests.TestEntities.Nesting
4+
{
5+
public class SubNestedModel : ISubNestedModel
6+
{
7+
public string BuiltInType { get; set; }
8+
}
9+
}

src/Simplify.Web/Bootstrapper/BaseBootstrapper.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ public virtual void RegisterDefaultModelBinders()
426426
/// </summary>
427427
public virtual void RegisterDefaultModelValidators()
428428
{
429-
BootstrapperFactory.ContainerProvider.Register<ValidationAttributesExecutor>(LifetimeType.Singleton);
429+
BootstrapperFactory.ContainerProvider.Register(r => new ValidationAttributesExecutor(), LifetimeType.Singleton);
430430
}
431431

432432
#endregion Simplify.Web types registration

src/Simplify.Web/Model/Validation/ValidationAttributesExecutor.cs

+31-15
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,20 @@ namespace Simplify.Web.Model.Validation
1212
/// </summary>
1313
public class ValidationAttributesExecutor : IModelValidator
1414
{
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="ValidationAttributesExecutor"/> class.
17+
/// </summary>
18+
/// <param name="nesting">if set to <c>true</c> then <see cref="ValidationAttributesExecutor"/> should validate nested and inherited properties.</param>
19+
public ValidationAttributesExecutor(bool nesting = true)
20+
{
21+
Nesting = nesting;
22+
}
23+
24+
/// <summary>
25+
/// Gets a value indicating whether <see cref="ValidationAttributesExecutor"/> should validate nested and inherited properties.
26+
/// </summary>
27+
public bool Nesting { get; }
28+
1529
/// <summary>
1630
/// Validates the specified model.
1731
/// </summary>
@@ -24,21 +38,6 @@ public void Validate<T>(T model, IDIResolver resolver)
2438
Validate(typeof(T), model, resolver);
2539
}
2640

27-
private static void Validate(Type type, object? value, IDIResolver resolver)
28-
{
29-
var properties = type.GetProperties();
30-
31-
foreach (var item in properties)
32-
{
33-
var currentItemValue = item.GetValue(value);
34-
35-
ValidateProperty(currentItemValue, item, resolver);
36-
37-
if (currentItemValue != default)
38-
Validate(item.PropertyType, currentItemValue, resolver);
39-
}
40-
}
41-
4241
/// <summary>
4342
/// Validates the specified value.
4443
/// </summary>
@@ -53,5 +52,22 @@ private static void ValidateProperty(object? value, PropertyInfo propertyInfo, I
5352
foreach (var attribute in validationAttributes)
5453
attribute.Validate(value, propertyInfo, resolver);
5554
}
55+
56+
private void Validate(Type type, object? value, IDIResolver resolver)
57+
{
58+
if (Nesting)
59+
if (type.BaseType != null && type.BaseType != typeof(object))
60+
Validate(type.BaseType, value, resolver);
61+
62+
foreach (var item in type.GetProperties())
63+
{
64+
var currentItemValue = item.GetValue(value);
65+
66+
ValidateProperty(currentItemValue, item, resolver);
67+
68+
if (Nesting && currentItemValue != default)
69+
Validate(item.PropertyType, currentItemValue, resolver);
70+
}
71+
}
5672
}
5773
}

0 commit comments

Comments
 (0)