Skip to content

Commit

Permalink
Workaround for HotChoc handling of arrays (#70)
Browse files Browse the repository at this point in the history
* #68

* fix: Turn the list into an array as expected, then validate
(ChilliCream/graphql-platform#4350)

* 7.2.1
  • Loading branch information
benmccallum authored Nov 6, 2021
1 parent b68cafd commit 1d1983c
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 105 deletions.
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<PackageIconUrl>https://github.com/benmccallum/fairybread/raw/master/logo-400x400.png</PackageIconUrl>
<PackageLicenseUrl>https://github.com/benmccallum/fairybread/blob/master/LICENSE</PackageLicenseUrl>

<Version>7.2.0</Version>
<Version>7.2.1</Version>

<FluentValidationVersion>10.0.0</FluentValidationVersion>
<HotChocolateVersion>11.0.9</HotChocolateVersion>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
{
Errors: [
{
Message: Unexpected Execution Error,
Path: {
Name: readWithArrayArg
},
Locations: [
{
Line: 1,
Column: 9
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'FooInputDto[]'.
}
}
]
Data: {
readWithArrayArg: SomeInteger: 1, SomeString: hello
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
{
Errors: [
{
Message: Unexpected Execution Error,
Path: {
Name: readWithArrayArg
},
Locations: [
{
Line: 1,
Column: 9
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'FooInputDto[]'.
}
}
]
Data: {
readWithArrayArg: SomeInteger: 1, SomeString: hello
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
{
Errors: [
{
Message: Unexpected Execution Error,
Path: {
Name: readWithArrayArg
},
Locations: [
{
Line: 1,
Column: 9
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'FooInputDto[]'.
}
}
]
Data: {
readWithArrayArg: SomeInteger: 1, SomeString: hello, SomeInteger: 1, SomeString: hello
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
{
Errors: [
{
Message: Unexpected Execution Error,
Message: 'Some Integer' must be equal to '1'.,
Code: FairyBread_ValidationError,
Path: {
Name: readWithArrayArg
},
Locations: [
{
Line: 1,
Column: 9
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'FooInputDto[]'.
Extensions: {
code: FairyBread_ValidationError,
argumentName: foos,
validatorName: ArrayOfFooInputDtoValidator,
errorCode: EqualValidator,
errorMessage: 'Some Integer' must be equal to '1'.,
attemptedValue: -1,
severity: Error,
formattedMessagePlaceholderValues: {
ComparisonValue: 1,
ComparisonProperty: ,
PropertyName: Some Integer,
PropertyValue: -1,
CollectionIndex: 0
},
propertyName: x[0].SomeInteger
}
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
{
Errors: [
{
Message: Unexpected Execution Error,
Message: 'Some Integer' must be equal to '1'.,
Code: FairyBread_ValidationError,
Path: {
Name: readWithArrayArg
},
Locations: [
{
Line: 1,
Column: 9
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'FooInputDto[]'.
Extensions: {
code: FairyBread_ValidationError,
argumentName: foos,
validatorName: ArrayOfFooInputDtoValidator,
errorCode: EqualValidator,
errorMessage: 'Some Integer' must be equal to '1'.,
attemptedValue: -1,
severity: Error,
formattedMessagePlaceholderValues: {
ComparisonValue: 1,
ComparisonProperty: ,
PropertyName: Some Integer,
PropertyValue: -1,
CollectionIndex: 0
},
propertyName: x[0].SomeInteger
}
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
{
Errors: [
{
Message: Unexpected Execution Error,
Message: 'Some Integer' must be equal to '1'.,
Code: FairyBread_ValidationError,
Path: {
Name: readWithArrayArg
},
Locations: [
{
Line: 1,
Column: 9
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'FooInputDto[]'.
Extensions: {
code: FairyBread_ValidationError,
argumentName: foos,
validatorName: ArrayOfFooInputDtoValidator,
errorCode: EqualValidator,
errorMessage: 'Some Integer' must be equal to '1'.,
attemptedValue: -1,
severity: Error,
formattedMessagePlaceholderValues: {
ComparisonValue: 1,
ComparisonProperty: ,
PropertyName: Some Integer,
PropertyValue: -1,
CollectionIndex: 0
},
propertyName: x[0].SomeInteger
}
},
{
Message: 'Some Integer' must be equal to '1'.,
Code: FairyBread_ValidationError,
Path: {
Name: readWithArrayArg
},
Extensions: {
code: FairyBread_ValidationError,
argumentName: foos,
validatorName: ArrayOfFooInputDtoValidator,
errorCode: EqualValidator,
errorMessage: 'Some Integer' must be equal to '1'.,
attemptedValue: -1,
severity: Error,
formattedMessagePlaceholderValues: {
ComparisonValue: 1,
ComparisonProperty: ,
PropertyName: Some Integer,
PropertyValue: -1,
CollectionIndex: 1
},
propertyName: x[1].SomeInteger
}
}
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,20 +289,51 @@
}
},
{
Message: Unexpected Execution Error,
Message: '' must be greater than '0'.,
Code: FairyBread_ValidationError,
Path: {
Name: arrayArgA
},
Locations: [
{
Line: 1,
Column: 424
}
],
Exception: {
$type: InvalidOperationException,
Type: InvalidOperationException,
Message: Cannot validate instances of type 'List`1'. This validator can only validate instances of type 'Nullable`1[]'.
Extensions: {
code: FairyBread_ValidationError,
argumentName: items,
validatorName: ArrayOfNullableIntValidator,
errorCode: GreaterThanValidator,
errorMessage: '' must be greater than '0'.,
attemptedValue: 0,
severity: Error,
formattedMessagePlaceholderValues: {
CollectionIndex: 0,
ComparisonValue: 0,
ComparisonProperty: ,
PropertyName: null,
PropertyValue: 0
},
propertyName: x[0]
}
},
{
Message: '' must be greater than '0'.,
Code: FairyBread_ValidationError,
Path: {
Name: arrayArgA
},
Extensions: {
code: FairyBread_ValidationError,
argumentName: items,
validatorName: ArrayOfNullableIntValidator,
errorCode: GreaterThanValidator,
errorMessage: '' must be greater than '0'.,
attemptedValue: 0,
severity: Error,
formattedMessagePlaceholderValues: {
CollectionIndex: 1,
ComparisonValue: 0,
ComparisonProperty: ,
PropertyName: null,
PropertyValue: 0
},
propertyName: x[1]
}
},
{
Expand Down
26 changes: 23 additions & 3 deletions src/FairyBread/ValidationMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using FluentValidation;
using FluentValidation.Results;
using HotChocolate.Resolvers;
using HotChocolate.Types;

namespace FairyBread
{
Expand Down Expand Up @@ -49,9 +51,27 @@ public async Task InvokeAsync(IMiddlewareContext context)
continue;
}

var isListType = argument.Type.IsListType();
Type? valueRuntimeType = null;
MethodInfo? toArrayMethod = null;
object? arrayValue = null;

foreach (var resolvedValidator in resolvedValidators)
{
var validationContext = new ValidationContext<object?>(value);
// Workaround for https://github.com/ChilliCream/hotchocolate/issues/4350
var valueToValidate = value;
if (isListType &&
!resolvedValidator.Validator.CanValidateInstancesOfType(value.GetType()))
{
valueRuntimeType ??= value.GetType();
toArrayMethod ??= valueRuntimeType.GetMethod("ToArray");
if (toArrayMethod != null)
{
valueToValidate = (arrayValue ??= toArrayMethod.Invoke(value, null));
}
}

var validationContext = new ValidationContext<object?>(valueToValidate);
var validationResult = await resolvedValidator.Validator.ValidateAsync(
validationContext,
context.RequestAborted);
Expand Down

0 comments on commit 1d1983c

Please sign in to comment.