When defining a function with single optional parameter, api returns 500 (Internal Server Error).
Microsoft.AspNet.OData 7.0.1
[ODataRoute("Users/GetFirstName()")]
public string GetFirstName()
{
return GetFirstName("Unknown");
}
[ODataRoute("Users/GetFirstName(firstName={firstName})")]
public string GetFirstName(string firstName)
{
return firstName;
}
var getFirstName = builder.EntityType<User>().Collection
.Function("GetFirstName")
.Returns<string>();
getFirstName.Parameter<string>("firstName").Optional().HasDefaultValue("Unknown");
http://localhost:63000/v1/Users/GetFirstName()
{
"@odata.context": "http://localhost:63000/v1/$metadata#Edm.String",
"value": "Unknown"
}
Status: 500 Internal Server Error
Server Error in '/' Application.
The path template 'Users/GetFirstName()' on the action 'GetFirstName' in controller 'Users' is not a valid OData path template. Bad Request - Error in query syntax.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The path template 'Users/GetFirstName()' on the action 'GetFirstName' in controller 'Users' is not a valid OData path template. Bad Request - Error in query syntax.
Example: https://github.com/flibustier7seas/odata-example/tree/optional-parameter#optional-parameter-not-working-for-function-with-single-argument
@flibustier7seas Optional parameter means the parameter maybe has default value. But for the function syntax, all parameters (include optional parameters) should be presented in the route template.
In your scenario, you should remove the first one and keep/change the second one as:
C#
[ODataRoute("Users/GetFirstName(firstName={firstName})")]
public string GetFirstName([FromODataUri]string firstName = "Unknown")
{
return firstName;
}
Hope it can help. Thanks.
@xuzhg
But for the function syntax, all parameters (include optional parameters) should be presented in the route template.
I can skip optional parameters in the route template for function with 2 parameters:
Request: http://localhost:63000/v1/Users/GetFullName(firstName='Foo')
var getFullName = builder.EntityType<User>().Collection
.Function("GetFullName")
.Returns<string>();
getFullName.Parameter<string>("firstName").Required();
getFullName.Parameter<string>("lastName").Optional().HasDefaultValue("Unknown");
[ODataRoute("Users/GetFullName(firstName={firstName})")]
public string GetFullName(string firstName)
{
return GetFullName(firstName, "Unknown");
}
Why cannot skip optional parameter in the route template for function with single optional parameter?
@flibustier7seas In my understanding, "optional" means its value can be optional, but not for the syntax. for a function or action, its syntax is function name plus the parameter type. That's different with the "method" in C#. I would like @mikepizzo can share his thoughts about the "optional"
@xuzhg
In my understanding, when a parameter is marked as "optional", it can be omitted when the function is called, as in "C#"
https://www.odata.org/blog/OData-401-Committee-Spec-Published/
Optional Function Parameters – Function parameters can be annotated as optional. Optional parameters may be omitted when invoking the function.
@raheph @xuzhg @mikepizzo any updates on this issue?
Any updates? Following.
@denious It should be fixed in the ODL. Would you please try the latest version and share us your finding. Thanks
Running Microsoft.AspNetCore.OData 7.1.0 I confirm the same buggy behavior as originally described:
Expected 200 in these scenarios:
Only scenario that works is the last one, the first two return 404:



Method signature:
[ODataRoute("GetSearchFilterOperators(filter={filter})")]
[HttpGet]
[Produces("application/json")]
[ProducesResponseType(typeof(ODataValue<IEnumerable<SearchFilterOperator>>), (int)HttpStatusCode.OK)]
public IQueryable<SearchFilterOperator> GetSearchFilterOperators([FromODataUri] string filter = null)
ODATA config for the function:
var getSearchFilerOperatorFunc = entityType.Collection
.Function("GetSearchFilterOperators")
.ReturnsCollection<SearchFilterOperator>();
var filterParam = getSearchFilerOperatorFunc.Parameter<string>("filter");
filterParam.Optional();
filterParam.HasDefaultValue(null);
Most helpful comment
Running Microsoft.AspNetCore.OData 7.1.0 I confirm the same buggy behavior as originally described:
Expected 200 in these scenarios:
Only scenario that works is the last one, the first two return 404:
Method signature:
ODATA config for the function: