Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select query throw an error on a dynamic property dictionary #1224

Open
TARGAZ opened this issue Apr 24, 2024 · 7 comments
Open

Select query throw an error on a dynamic property dictionary #1224

TARGAZ opened this issue Apr 24, 2024 · 7 comments

Comments

@TARGAZ
Copy link

TARGAZ commented Apr 24, 2024

Hello,

On a entity with a complex property that has dynamic property dictionary. I can't do a select clause on this complex property.

Assemblies affected
Microsoft.AspNetCore.OData 8.2.5

Reproduce steps
1.Clone the repository : https://github.com/TARGAZ/ODataSelectDynamicPropertyBug
2.Run
3.Try queries :

Expected result
First query : https://localhost:7092/odata/customers?$select=Name

{
  "@odata.context": "https://localhost:7092/odata/$metadata#Customers",
  "value": [
    {
      "Name": {
        "en": "english",
        "fr": "french"
      }
    },
    {
      "Name": {
        "en": "english",
        "fr": "french"
      }
    },
    {
      "Name": {
        "en": "english",
        "fr": "french"
      }
    }
  ]
}

Second Query : https://localhost:7092/odata/customers?$select=Name/en

{
  "@odata.context": "https://localhost:7092/odata/$metadata#Customers",
  "value": [
    {
      "Name": {
        "en": "english"
      }
    },
    {
      "Name": {
        "en": "english"
      }
    },
    {
      "Name": {
        "en": "english"
      }
    }
  ]
}

Actual result
The error is the same for both queries :

The query specified in the URI is not valid. The given model does not contain the type 'System.Collections.Generic.KeyValuePair`2[[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]'.

Stack trace :

at Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext..ctor(QueryBinderContext context, ODataQuerySettings querySettings, Type clrType)
at Microsoft.AspNetCore.OData.Query.Expressions.SelectExpandBinder.ProjectAsWrapper(QueryBinderContext context, Expression source, SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmNavigationSource navigationSource, OrderByClause orderByClause, ComputeClause computeClause, Nullable`1 topOption, Nullable`1 skipOption, Nullable`1 modelBoundPageSize)
at Microsoft.AspNetCore.OData.Query.Expressions.SelectExpandBinder.BuildSelectedProperty(QueryBinderContext context, Expression source, IEdmStructuredType structuredType, IEdmStructuralProperty structuralProperty, PathSelectItem pathSelectItem, IList`1 includedProperties)
at Microsoft.AspNetCore.OData.Query.Expressions.SelectExpandBinder.BuildPropertyContainer(QueryBinderContext context, Expression source, IEdmStructuredType structuredType, IDictionary`2 propertiesToExpand, IDictionary`2 propertiesToInclude, IList`1 computedProperties, ISet`1 autoSelectedProperties, Boolean isSelectingOpenTypeSegments, Boolean isSelectedAll)
at Microsoft.AspNetCore.OData.Query.Expressions.SelectExpandBinder.ProjectElement(QueryBinderContext context, Expression source, SelectExpandClause selectExpandClause, IEdmStructuredType structuredType, IEdmNavigationSource navigationSource)
at Microsoft.AspNetCore.OData.Query.Expressions.SelectExpandBinder.BindSelectExpand(SelectExpandClause selectExpandClause, QueryBinderContext context)
at Microsoft.AspNetCore.OData.Query.Expressions.BinderExtensions.ApplyBind(ISelectExpandBinder binder, IQueryable source, SelectExpandClause selectExpandClause, QueryBinderContext context)
at Microsoft.AspNetCore.OData.Query.SelectExpandQueryOption.ApplyTo(IQueryable queryable, ODataQuerySettings settings)
at Microsoft.AspNetCore.OData.Query.ODataQueryOptions.ApplySelectExpand[T](T entity, ODataQuerySettings querySettings)
at Microsoft.AspNetCore.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query, ODataQuerySettings querySettings)
at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions)
at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.ExecuteQuery(Object responseValue, IQueryable singleResultCollection, ControllerActionDescriptor actionDescriptor, HttpRequest request)
at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuted(ActionExecutedContext actionExecutedContext, Object responseValue, IQueryable singleResultCollection, ControllerActionDescriptor actionDescriptor, HttpRequest request)
@TARGAZ TARGAZ added the bug Something isn't working label Apr 24, 2024
@TARGAZ TARGAZ changed the title Select queries return an error on a dynamic property dictionary. Select queries return an error on a dynamic property dictionary Apr 24, 2024
@TARGAZ TARGAZ changed the title Select queries return an error on a dynamic property dictionary Select query return an error on a dynamic property dictionary Apr 24, 2024
@TARGAZ TARGAZ changed the title Select query return an error on a dynamic property dictionary Select query throw an error on a dynamic property dictionary Apr 24, 2024
@julealgon
Copy link
Contributor

On a entity with a complex property that has dynamic property dictionary.

Would you mind sharing a sample of what that model looks like as well?

@TARGAZ
Copy link
Author

TARGAZ commented Apr 24, 2024

You can find the EDM model here : https://github.com/TARGAZ/ODataSelectDynamicPropertyBug/blob/main/Program.cs

var modelBuilder = new ODataModelBuilder();

var customerType = modelBuilder.EntityType<Customer>();
customerType.HasKey(c => c.Id);
customerType.ComplexProperty(c => c.Name);

Type localizableStringType = typeof(LocalizableString);
ComplexTypeConfiguration localizableStringConfiguration = modelBuilder.AddComplexType(localizableStringType);
localizableStringConfiguration.AddDynamicPropertyDictionary(localizableStringType.GetProperty(nameof(LocalizableString.ExtendedProperties)));

modelBuilder.EntitySet<Customer>("Customers");

@julealgon
Copy link
Contributor

Oh I'm dumb, I didn't realize you provided a sample repo there, my bad @TARGAZ .

@julealgon
Copy link
Contributor

Based on your code..... can you check whether replacing IDictionary on the ExtendedProperties property with Dictionary (the concrete class) makes a difference here?

        public Dictionary<string, object> ExtendedProperties

IIRC, OData's EDM builder won't automatically match interfaces to implementations when they are found in the model. You either need to specify the type explicitly in that case, or just type it to the concrete type and it will be picked up automatically.

Let us know if that changes the error in any way.

@TARGAZ
Copy link
Author

TARGAZ commented Apr 24, 2024

Unfortunately, this doesn't work I have the same error. Note that the $filter works on this property.

@xuzhg
Copy link
Member

xuzhg commented Apr 29, 2024

@TARGAZ OData needs the 'model type' as POCO class, so your 'LocalizableString' can't be treated correctly since it's derived from 'ReadOnlyDictionary< >'.

If you replace your 'LocalizableString' definition using composition, not using inheritance, it should work:

public sealed class LocalizableString/* : ReadOnlyDictionary<string, string>*/
{
    private IDictionary<string, object> _values;
    ......
}

image

@xuzhg xuzhg added investigated and removed bug Something isn't working labels Apr 29, 2024
@TARGAZ
Copy link
Author

TARGAZ commented May 3, 2024

Hello,
Thank you for your help. It works really well :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants