OData / OData/AspNetCoreOData

StringAsEnumResolver not working

Open
#204 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

EFCore followup
Dominant language
C#
Stars
505
Forks
186
PR merge metrics
No merged PRs in 30d

Description

Using latest 8.0.0-rc3.

services.AddControllers()
    .AddOData(opt => opt.Count().Filter().Expand().Select().OrderBy().SetMaxTop(100)
        .AddModel(string.Empty, GetEdmModel(),
            builder =>
            {
                builder.AddService(Microsoft.OData.ServiceLifetime.Singleton, typeof(ODataUriResolver), sp => new StringAsEnumResolver() { EnableCaseInsensitive = true });
            })
        .Conventions.Add(new OdataConvention()))

With the above code to configure StringAsEnumResolver, I'm still not able to use strings to filter enums. I've scoured the internet to no avail.

What am I missing?

Error from $filter=contactType eq 'person':

{
  "error": {
    "code": "",
    "message": "The query specified in the URI is not valid. The string 'person' is not a valid enumeration type constant.",
    "details": [
      
    ],
    "innererror": {
      "message": "The string 'person' is not a valid enumeration type constant.",
      "type": "Microsoft.OData.ODataException",
      "stacktrace": "   at Microsoft.OData.UriParser.MetadataBindingUtils.ConvertToTypeIfNeeded(SingleValueNode source, IEdmTypeReference targetTypeReference)\n   at Microsoft.OData.UriParser.BinaryOperatorBinder.PromoteOperandTypes(BinaryOperatorKind binaryOperatorKind, SingleValueNode& left, SingleValueNode& right, TypeFacetsPromotionRules facetsPromotionRules)\n   at Microsoft.OData.UriParser.ODataUriResolver.PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperatorKind, SingleValueNode& leftNode, SingleValueNode& rightNode, IEdmTypeReference& typeReference)\n   at Microsoft.OData.UriParser.StringAsEnumResolver.PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperatorKind, SingleValueNode& leftNode, SingleValueNode& rightNode, IEdmTypeReference& typeReference)\n   at Microsoft.OData.UriParser.BinaryOperatorBinder.BindBinaryOperator(BinaryOperatorToken binaryOperatorToken)\n   at Microsoft.OData.UriParser.MetadataBinder.BindBinaryOperator(BinaryOperatorToken binaryOperatorToken)\n   at Microsoft.OData.UriParser.MetadataBinder.Bind(QueryToken token)\n   at Microsoft.OData.UriParser.FilterBinder.BindFilter(QueryToken filter)\n   at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilterImplementation(String filter, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo)\n   at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilter()\n   at Microsoft.AspNetCore.OData.Query.FilterQueryOption.get_FilterClause()\n   at Microsoft.AspNetCore.OData.Query.Validator.FilterQueryValidator.Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)\n   at Microsoft.AspNetCore.OData.Query.FilterQueryOption.Validate(ODataValidationSettings validationSettings)\n   at Microsoft.AspNetCore.OData.Query.Validator.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\n   at Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\n   at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ValidateQuery(HttpRequest request, ODataQueryOptions queryOptions)\n   at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuting(ActionExecutingContext actionExecutingContext)"
    }
  }
}

Error from $filter=contains(tolower(contactType),'person'):

{
  "error": {
    "code": "",
    "message": "The query specified in the URI is not valid. No function signature for the function with name 'tolower' matches the specified arguments. The function signatures considered are: tolower(Edm.String Nullable=true).",
    "details": [
      
    ],
    "innererror": {
      "message": "No function signature for the function with name 'tolower' matches the specified arguments. The function signatures considered are: tolower(Edm.String Nullable=true).",
      "type": "Microsoft.OData.ODataException",
      "stacktrace": "   at Microsoft.OData.UriParser.FunctionCallBinder.MatchSignatureToUriFunction(String functionCallToken, SingleValueNode[] argumentNodes, IList`1 nameSignatures)\n   at Microsoft.OData.UriParser.FunctionCallBinder.BindAsUriFunction(FunctionCallToken functionCallToken, List`1 argumentNodes)\n   at Microsoft.OData.UriParser.FunctionCallBinder.BindFunctionCall(FunctionCallToken functionCallToken)\n   at Microsoft.OData.UriParser.MetadataBinder.BindFunctionCall(FunctionCallToken functionCallToken)\n   at Microsoft.OData.UriParser.MetadataBinder.Bind(QueryToken token)\n   at Microsoft.OData.UriParser.MetadataBinder.BindFunctionParameter(FunctionParameterToken token)\n   at Microsoft.OData.UriParser.MetadataBinder.Bind(QueryToken token)\n   at Microsoft.OData.UriParser.FunctionCallBinder.<BindFunctionCall>b__7_0(FunctionParameterToken ar)\n   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()\n   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\n   at Microsoft.OData.UriParser.FunctionCallBinder.BindFunctionCall(FunctionCallToken functionCallToken)\n   at Microsoft.OData.UriParser.MetadataBinder.BindFunctionCall(FunctionCallToken functionCallToken)\n   at Microsoft.OData.UriParser.MetadataBinder.Bind(QueryToken token)\n   at Microsoft.OData.UriParser.FilterBinder.BindFilter(QueryToken filter)\n   at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilterImplementation(String filter, ODataUriParserConfiguration configuration, ODataPathInfo odataPathInfo)\n   at Microsoft.OData.UriParser.ODataQueryOptionParser.ParseFilter()\n   at Microsoft.AspNetCore.OData.Query.FilterQueryOption.get_FilterClause()\n   at Microsoft.AspNetCore.OData.Query.Validator.FilterQueryValidator.Validate(FilterQueryOption filterQueryOption, ODataValidationSettings settings)\n   at Microsoft.AspNetCore.OData.Query.FilterQueryOption.Validate(ODataValidationSettings validationSettings)\n   at Microsoft.AspNetCore.OData.Query.Validator.ODataQueryValidator.Validate(ODataQueryOptions options, ODataValidationSettings validationSettings)\n   at Microsoft.AspNetCore.OData.Query.ODataQueryOptions.Validate(ODataValidationSettings validationSettings)\n   at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ValidateQuery(HttpRequest request, ODataQueryOptions queryOptions)\n   at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuting(ActionExecutingContext actionExecutingContext)"
    }
  }
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the StringAsEnumResolver configuration in the issue and trace the reported calls through ODataUriResolver, StringAsEnumResolver, and ODataQueryOptionParser. Reproduce both filter expressions, then determine why the configured resolver does not accept the enum string and verify the supported behavior or fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.