@@ -157,7 +157,8 @@ public override void Handle(OperationImportSegment segment)
157157 {
158158 _navigationSource = segment . EntitySet ;
159159
160- IEdmActionImport actionImport = segment . OperationImports . Single ( ) as IEdmActionImport ;
160+ IEdmOperationImport operationImport = segment . OperationImports . Single ( ) ;
161+ IEdmActionImport actionImport = operationImport as IEdmActionImport ;
161162
162163 if ( actionImport != null )
163164 {
@@ -166,14 +167,14 @@ public override void Handle(OperationImportSegment segment)
166167 }
167168 else
168169 {
170+ IEdmFunctionImport function = ( IEdmFunctionImport ) operationImport ;
171+
169172 _pathTemplate . Add ( ODataSegmentKinds . UnboundFunction ) ; // unbound function
170173
171174 // Translate the nodes in ODL path to string literals as parameter of UnboundFunctionPathSegment.
172175 Dictionary < string , string > parameterValues = segment . Parameters . ToDictionary (
173176 parameterValue => parameterValue . Name ,
174- parameterValue => TranslateNode ( parameterValue . Value ) ) ;
175-
176- IEdmFunctionImport function = ( IEdmFunctionImport ) segment . OperationImports . Single ( ) ;
177+ parameterValue => TranslateNode ( parameterValue . Value , function . Name , parameterValue . Name ) ) ;
177178
178179 IEnumerable < string > parameters = parameterValues . Select ( v => String . Format ( CultureInfo . InvariantCulture , "{0}={1}" , v . Key , v . Value ) ) ;
179180 string literal = String . Format ( CultureInfo . InvariantCulture , "{0}({1})" , function . Name , String . Join ( "," , parameters ) ) ;
@@ -190,7 +191,8 @@ public override void Handle(OperationSegment segment)
190191 {
191192 _navigationSource = segment . EntitySet ;
192193
193- IEdmAction action = segment . Operations . Single ( ) as IEdmAction ;
194+ IEdmOperation edmOperation = segment . Operations . Single ( ) ;
195+ IEdmAction action = edmOperation as IEdmAction ;
194196
195197 if ( action != null )
196198 {
@@ -199,16 +201,15 @@ public override void Handle(OperationSegment segment)
199201 }
200202 else
201203 {
204+ IEdmFunction function = ( IEdmFunction ) edmOperation ;
202205 _pathTemplate . Add ( ODataSegmentKinds . Function ) ; // function
203206
204207 // Translate the nodes in ODL path to string literals as parameter of BoundFunctionPathSegment.
205208 Dictionary < string , string > parameterValues = segment . Parameters . ToDictionary (
206209 parameterValue => parameterValue . Name ,
207- parameterValue => TranslateNode ( parameterValue . Value ) ) ;
210+ parameterValue => TranslateNode ( parameterValue . Value , function . Name , parameterValue . Name ) ) ;
208211
209212 // TODO: refactor the function literal for parameter alias
210- IEdmFunction function = ( IEdmFunction ) segment . Operations . Single ( ) ;
211-
212213 IEnumerable < string > parameters = parameterValues . Select ( v => String . Format ( CultureInfo . InvariantCulture , "{0}={1}" , v . Key , v . Value ) ) ;
213214 string literal = String . Format ( CultureInfo . InvariantCulture , "{0}({1})" , function . FullName ( ) , String . Join ( "," , parameters ) ) ;
214215
@@ -414,9 +415,17 @@ private static string TranslateKeySegmentValue(object value)
414415 return ODataUriUtils . ConvertToUriLiteral ( value , ODataVersion . V4 ) ;
415416 }
416417
417- private static string TranslateNode ( object node )
418+ private static string TranslateNode ( object node , string functionName , string parameterName )
418419 {
419- Contract . Assert ( node != null ) ;
420+ // If the function parameter is null, for example myFunction(param=null),
421+ // the input node here is not null, it is a contant node with a value as "null".
422+ // However, if a function call (or key) using parameter alias but without providing the parameter alias value,
423+ // the input node here is a null.
424+ if ( node == null )
425+ {
426+ // We can't throw ODataException here because ODataException will be caught and return 404 response with empty message.
427+ throw new InvalidOperationException ( Error . Format ( SRResources . MissingConvertNode , parameterName , functionName ) ) ;
428+ }
420429
421430 ConstantNode constantNode = node as ConstantNode ;
422431 if ( constantNode != null )
@@ -440,7 +449,7 @@ private static string TranslateNode(object node)
440449 ConvertNode convertNode = node as ConvertNode ;
441450 if ( convertNode != null )
442451 {
443- return TranslateNode ( convertNode . Source ) ;
452+ return TranslateNode ( convertNode . Source , functionName , parameterName ) ;
444453 }
445454
446455 ParameterAliasNode parameterAliasNode = node as ParameterAliasNode ;
0 commit comments