Search code examples
c#.netodata

Using an Unbound Action with Parameters in the OData


When parsing an OData URI with unbound actions and parameters, the following exception is thrown: The request URI is not valid. The segment 'TestAction' cannot include key predicates, however it may end with empty parenthesis. The code below reproduces the exception:

        var builder = new ODataConventionModelBuilder
        {
            Namespace = "Test",
            ContainerName = "Test"
        };

        var action = builder.Action("TestAction").Returns<long>();

        action.Parameter<int?>("x");
        action.Parameter<int?>("y");

        var model = builder.GetEdmModel();

        var parser = new ODataUriParser(model, new Uri("TestAction(x=1,y=2)", UriKind.Relative));

        var path = parser.ParsePath();

I've investigated the Microsoft.OData.Core source codes and found this in the FunctionOverloadResolver class:

        try
        {
            if (parameterNames.Count > 0)
            {
                // In this case we have to return a function so filter out actions because the number of parameters > 0.
                candidateMatchingOperationImports = resolver.ResolveOperationImports(model, identifier).RemoveActionImports(out foundActionImportsWhenLookingForFunctions).FilterFunctionsByParameterNames(parameterNames, resolver.EnableCaseInsensitive).Cast<IEdmOperationImport>().ToList();
            }
            else
            {
                candidateMatchingOperationImports = resolver.ResolveOperationImports(model, identifier).ToList();
            }
        }
        catch (Exception exc)
        {
            if (!ExceptionUtils.IsCatchableExceptionType(exc))
            {
                throw;
            }

            throw new ODataException(ODataErrorStrings.FunctionOverloadResolver_FoundInvalidOperationImport(identifier), exc);
        }

        if (foundActionImportsWhenLookingForFunctions.Count > 0)
        {
            throw ExceptionUtil.CreateBadRequestError(ODataErrorStrings.RequestUriProcessor_SegmentDoesNotSupportKeyPredicates(identifier));
        }

Why the resolver class needs to filter out the actions when the operation has parameters?


Solution

  • I've finally figured out the problem. The action parameters should be on the request payload. So the URI should look like:

        var parser = new ODataUriParser(model, new Uri("TestAction", UriKind.Relative));