I was trying to use AutoQuery with a NodaTime.LocalDate on a query parameter and I get the following exception when I try to filter using that date field, specifically >MyDate=2020-01-01 (ordering is unaffected):
[MyEndpoint: 5/23/2016 4:19:51 PM]: [REQUEST: {}] System.InvalidCastException: Invalid cast from 'System.String' to 'NodaTime.LocalDate'. at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) at ServiceStack.TypedQuery`2.AppendUntypedQueries(SqlExpression`1 q, Dictionary`2 dynamicParams, String defaultTerm, IAutoQueryOptions options, Dictionary`2 aliases) at ServiceStack.TypedQuery`2.CreateQuery(IDbConnection db, IQueryDb dto, Dictionary`2 dynamicParams, IAutoQueryOptions options) at ServiceStack.AutoQuery.CreateQuery[From](IQueryDb`1 dto, Dictionary`2 dynamicParams, IRequest req) at ServiceStack.AutoQueryServiceBase.Exec[From](IQueryDb`1 dto) at ServiceStack.Host.ServiceRunner`1.Execute(IRequest request, Object instance, TRequest requestDto)
I tracked it down to this line of code that uses Convert.ChangeType(...) because NodaTime.LocalDate is a struct and not an enum:
var value = strValue == null ?
null
: isMultiple ?
TypeSerializer.DeserializeFromString(strValue, Array.CreateInstance(fieldType, 0).GetType())
: fieldType == typeof(string) ?
strValue
: fieldType.IsValueType && !fieldType.IsEnum ? //This is true for NodaTime.LocalDate
Convert.ChangeType(strValue, fieldType) : //NodaTime.LocalDate does not implement IConvertible, so this throws
TypeSerializer.DeserializeFromString(strValue, fieldType);
I'm using my NodaTime ServiceStack serialization library so the behavior of TypeSerializer.DeserializeFromString(strValue, fieldType) is what I actually want in this case.
Workarounds I see are:
- Use
MyDateDateBetween=2020-01-01,9999-12-31in the query string as that code path uses the custom serialization I have specified (cumbersome) - Use
DateTimeinstead ofNodaTime.LocalDate(I want to useNodaTime.LocalDate) - Not use AutoQuery (I want to)
NodaTime.LocalDateimplementsIConvertible(not likely)
Is there another way to get auto query filters to work with value types that don't implement IConvertible?
I've just added wrapped these lines in a new
ChangeTo()extension method with an extra check to check for implementingIConvertiblein this commit:And changed AutoQuery to use it so NodaTime's LocalDate should now fall through to the TypeSerializer.
This change is available from v4.0.57 that's now available on MyGet.