Skip to content

CustomUriFunctions do not support nullable parameters #1533

@Xriuk

Description

@Xriuk

Assemblies affected
Which assemblies and versions are known to be affected e.g. ASP.NET Core OData 8.2.4 (but I feel it affects all the versions)

Describe the bug
When adding a custom function for a nullable type when binding that function an exception is thrown:

Expression of type 'System.Int32' cannot be used for parameter of type 'System.Nullable`1[System.Int32]' of method 'System.String MyMethod(System.Nullable`1[System.Int32])' (Parameter 'arg0')
   at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
   at Microsoft.AspNetCore.OData.Query.Expressions.ExpressionBinderHelper.MakeFunctionCall(MemberInfo member, ODataQuerySettings querySettings, Expression[] arguments)
   at Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCustomMethodExpressionOrNull(SingleValueFunctionCallNode node, QueryBinderContext context)
...

Reproduce steps

public static string MyMethod(int? value){
    ...
}

...

ODataUriFunctions.AddCustomUriFunction("myFunc", new FunctionSignatureWithReturnType(
	EdmCoreModel.Instance.GetString(false),
	EdmCoreModel.Instance.GetInt32(true)
), typeof(...).GetMethod("MyMethod"));

...

// Invoke the func in the query
/...?$compute=myFunc(...) as Result&$select=Result

Expected behavior
Custom Uri functions with nullable parameters should work as expected.

Additional context
I think that the culprit is here:

// if the argument is of type Nullable<T>, then translate the argument to Nullable<T>.Value as none
// of the canonical functions have overloads for Nullable<> arguments.
functionCallArguments = ExtractValueFromNullableArguments(functionCallArguments);

It strips away Nullable parameters regardless because canonical functions don't have overloads for them (but custom ones might have).

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions