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

odata.metadata=full throws exceptions with $apply #1280

Open
Xriuk opened this issue Jul 15, 2024 · 3 comments
Open

odata.metadata=full throws exceptions with $apply #1280

Xriuk opened this issue Jul 15, 2024 · 3 comments
Assignees
Labels
bug Something isn't working investigating P2

Comments

@Xriuk
Copy link

Xriuk commented Jul 15, 2024

Assemblies affected
ASP.NET Core OData 8.2.4

Describe the bug
When using the query option $apply with odata.metadata=full the results an exception is thrown.

Reproduce steps
Reproduce steps
A GET request to:

https://.../ProductIdentifiers?$apply=groupby((ProductCode))

with header:

Accept application/json;odata.metadata=full

Throws:

System.NullReferenceException: Object reference not set to an instance of an object.
14:13:19:700	   at Microsoft.OData.UriUtils.UriToString(Uri uri)
14:13:19:700	   at Microsoft.OData.Evaluation.ODataConventionalUriBuilder.AppendSegment(Uri baseUri, String segment, Boolean escapeSegment)
14:13:19:700	   at Microsoft.OData.Evaluation.ODataConventionalUriBuilder.BuildNavigationLinkUri(Uri baseUri, String navigationPropertyName)
14:13:19:700	   at Microsoft.OData.Evaluation.ODataConventionalEntityMetadataBuilder.GetNavigationLinkUri(String navigationPropertyName, Uri navigationLinkUrl, Boolean hasNestedResourceInfoUrl)
14:13:19:700	   at Microsoft.OData.ODataNestedResourceInfo.get_Url()
14:13:19:700	   at Microsoft.OData.JsonLight.ODataJsonLightResourceSerializer.WriteNavigationLinkMetadataAsync(ODataNestedResourceInfo nestedResourceInfo, IDuplicatePropertyNameChecker duplicatePropertyNameChecker)
14:13:19:700	   at Microsoft.OData.JsonLight.ODataJsonLightWriter.<StartNestedResourceInfoWithContentAsync>g__StartNestedResourceInfoWithContentInnerAsync|79_0(ODataNestedResourceInfo innerNestedResourceInfo)
14:13:19:700	   at Microsoft.OData.ODataWriterCore.<>c.<<CheckForNestedResourceInfoWithContentAsync>b__204_1>d.MoveNext()
14:13:19:700	--- End of stack trace from previous location ---
14:13:19:700	   at Microsoft.OData.ODataWriterCore.InterceptExceptionAsync[TArg0](Func`3 action, TArg0 arg0)
14:13:19:700	   at Microsoft.OData.ODataWriterCore.CheckForNestedResourceInfoWithContentAsync(ODataPayloadKind contentPayloadKind, ODataItem contentPayload)
14:13:19:700	   at Microsoft.OData.ODataWriterCore.WriteStartResourceImplementationAsync(ODataResource resource)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteDynamicTypeResourceAsync(Object graph, ODataWriter writer, IEdmTypeReference expectedType, ODataSerializerContext writeContext)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteDynamicTypeResourceAsync(Object graph, ODataWriter writer, IEdmTypeReference expectedType, ODataSerializerContext writeContext)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteResourceAsync(Object graph, ODataWriter writer, ODataSerializerContext writeContext, IEdmTypeReference expectedType)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSerializer.WriteObjectInlineAsync(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteResourceSetItemAsync(Object item, IEdmStructuredTypeReference elementType, Boolean isUntypedCollection, IEdmTypeReference resourceSetType, ODataWriter writer, IODataEdmTypeSerializer resourceSerializer, ODataSerializerContext writeContext)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteResourceSetAsync(IEnumerable enumerable, IEdmTypeReference resourceSetType, ODataWriter writer, ODataSerializerContext writeContext)
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.Serialization.ODataResourceSetSerializer.WriteObjectInlineAsync(Object graph, IEdmTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
14:13:19:700	   at Tecnoware.Gestionale.OData.GroupByODataResourceSetSerializer.WriteObjectAsync(Object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) in C:\DevOps\Tecnoware.Gestionale\Backend\OData\GroupByODataResourceSetSerializer.cs:line 21
14:13:19:700	   at Microsoft.AspNetCore.OData.Formatter.ODataOutputFormatterHelper.WriteToStreamAsync(Type type, Object value, IEdmModel model, ODataVersion version, Uri baseAddress, MediaTypeHeaderValue contentType, HttpRequest request, IHeaderDictionary requestHeaders, IODataSerializerProvider serializerProvider)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
14:13:19:700	--- End of stack trace from previous location ---
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
14:13:19:700	   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
14:13:19:700	   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
14:13:19:700	   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
14:13:19:700	--- End of stack trace from previous location ---
14:13:19:700	   at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext()
14:13:19:700	--- End of stack trace from previous location ---
14:13:19:700	   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
14:13:19:700	   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.OData.Routing.ODataRouteDebugMiddleware.Invoke(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
14:13:19:700	   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
14:13:19:700	   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
14:13:19:700	   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.Watch.BrowserRefresh.BrowserRefreshMiddleware.InvokeAsync(HttpContext context)
14:13:19:700	   at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

Data Model

public class ProductIdentifier{
    [Key]
    public string ProductCode {get; set;}

    [Key]
    public id OwnerId {get; set;}

    [Key]
    public string OwnerProductCode {get; set;}
}

EDM (CSDL) Model

<EntityType Name="ProductIdentifier">
    <Key>
        <PropertyRef Name="ProductCode" />
        <PropertyRef Name="OwnerId" />
        <PropertyRef Name="OwnerProductCode" />
    </Key>
    <Property Name="ProductCode" Type="Edm.String" Nullable="false" />
    <Property Name="OwnerId" Type="Edm.Int32" Nullable="false" />
    <Property Name="OwnerProductCode" Type="Edm.String" Nullable="false" />
    ...
</EntityType>
...
<EntitySet Name="ProductIdentifiers" EntityType="Models.Products.ProductIdentifier" />

Additional context
I guess this has something to do with the computation of annotations "@odata.id" for which the required data is missing. The returned as per specs has the same type as the original entity set, but entities returned there are not original entities but aggregations instead, so any annotation should be null I guess.
While without odata.metadata=full the response is generated correctly, but "@odata.id" annotations are present (even if not requested), with the correct "null" value

@Xriuk Xriuk added the bug Something isn't working label Jul 15, 2024
@Xriuk
Copy link
Author

Xriuk commented Jul 15, 2024

Could be somehow related to #1265 ?

@gathogojr gathogojr added the P2 label Jul 16, 2024
@gathogojr gathogojr self-assigned this Jul 16, 2024
@peterkovecses
Copy link

In my experience, if I explicitly select the property in the query on the basis of which the grouping takes place, no exception is thrown and the response is complete.
For example:

?$select=ProductCode&$apply=groupby((ProductCode))

@Xriuk
Copy link
Author

Xriuk commented Sep 13, 2024

In my experience, if I explicitly select the property in the query on the basis of which the grouping takes place, no exception is thrown and the response is complete. For example:

?$select=ProductCode&$apply=groupby((ProductCode))

Yes, this may work, but it should not be needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working investigating P2
Projects
None yet
Development

No branches or pull requests

3 participants