diff --git a/ZWebAPI/ExtensionMethods/SummaryParametersExtensions.cs b/ZWebAPI/ExtensionMethods/SummaryParametersExtensions.cs index 9636c0a..088e5b2 100644 --- a/ZWebAPI/ExtensionMethods/SummaryParametersExtensions.cs +++ b/ZWebAPI/ExtensionMethods/SummaryParametersExtensions.cs @@ -68,7 +68,20 @@ public static bool HasFilter(this ISummaryParameters parameters, string property return null; } - switch (Type.GetTypeCode(resultType)) + // Nullable is unwrapped before anything asks what the type is. Type.GetTypeCode + // answers Object for Nullable, not Int64, so a nullable column fell through to + // the default branch and Convert.ChangeType threw -- it cannot produce a Nullable: + // + // InvalidCastException: Invalid cast from 'System.String' to + // 'System.Nullable`1[[System.Int64, ...]]' + // + // Filtering by any nullable property therefore failed before a row was read. + // IsEnum is false for Nullable for the same reason, so nullable enums are + // covered by unwrapping too. Returning the underlying value boxed is what callers + // already expect: RunFilter converts the constant to the member's own type. + Type targetType = Nullable.GetUnderlyingType(resultType) ?? resultType; + + switch (Type.GetTypeCode(targetType)) { case TypeCode.Boolean: if (jsonValue.ValueKind == JsonValueKind.String && bool.TryParse(jsonValue.GetString(), out bool boolResult)) @@ -171,11 +184,11 @@ public static bool HasFilter(this ISummaryParameters parameters, string property return null; } - if (resultType.IsEnum) + if (targetType.IsEnum) { - return Enum.Parse(resultType, rawValue.ToString() ?? string.Empty); + return Enum.Parse(targetType, rawValue.ToString() ?? string.Empty); } - return Convert.ChangeType(rawValue, resultType); + return Convert.ChangeType(rawValue, targetType); } } return null;