-
Notifications
You must be signed in to change notification settings - Fork 158
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
$apply=aggregate returns only JSON payload #1144
Comments
@audacity76 did you also observe this issue when using unbound functions? |
@habbes In my case it was a bound function. It happened when using the aggregate function on an endpoint |
We've confirmed that the current output does not match what's expected and that the response should be a standard OData response. We'll investigate and work on a fix. |
I can confirm that is still present with AspNetCoreOData Version 8.2.5, using $apply=aggregate but also $apply=groupby |
+1, from a quick look at the code I see that there is no serializer being selected because here (I guess)
the type IEnumerable<GroupByWrapper> cannot get a corresponding IEdmType , thus no serializer is being selected.
|
Quick fix: public class CustomODataSerializerProvider : ODataSerializerProvider {
private readonly IServiceProvider _serviceProvider;
public CustomODataSerializerProvider(IServiceProvider serviceProvider) :
base(serviceProvider) {
_serviceProvider = serviceProvider;
}
public override IODataSerializer GetODataPayloadSerializer(Type type, HttpRequest request) {
// Handle GroupByWrapper
var ienumerable = type.GetGenericBaseType(typeof(IEnumerable<>))?.GetGenericArguments()[0];
while(ienumerable != null) {
// Here you could also instantiate it directly with new GroupByODataResourceSetSerializer(...)
if(ienumerable.FullName == "Microsoft.AspNetCore.OData.Query.Wrapper.GroupByWrapper")
return _serviceProvider.GetRequiredService<GroupByODataResourceSetSerializer>();
if (ienumerable.BaseType != null && ienumerable.BaseType != typeof(object))
ienumerable = ienumerable.BaseType;
else
ienumerable = null;
}
return base.GetODataPayloadSerializer(type, request);
}
}
public class GroupByODataResourceSetSerializer : ODataResourceSetSerializer {
public GroupByODataResourceSetSerializer(IODataSerializerProvider serializerProvider) :
base(serializerProvider) {}
public override async Task WriteObjectAsync(object graph, Type type, ODataMessageWriter messageWriter, ODataSerializerContext writeContext) {
IEdmEntitySetBase entitySet = (writeContext.NavigationSource as IEdmEntitySetBase)!;
// The resource type should be the original collection before GroupBy so we retrieve it from the path
var pathType = writeContext.Path.LastSegment.EdmType.AsElementType();
IEdmTypeReference resourceSetType = new EdmCollectionTypeReference(new EdmCollectionType(pathType is IEdmEntityType ? new EdmEntityTypeReference((IEdmEntityType)pathType, false) : new EdmComplexTypeReference((IEdmComplexType)pathType, false)));
var resourceType = resourceSetType.AsCollection().ElementType().AsStructured();
ODataWriter writer = await messageWriter.CreateODataResourceSetWriterAsync(entitySet, resourceType.StructuredDefinition())
.ConfigureAwait(false);
await WriteObjectInlineAsync(graph, resourceSetType, writer, writeContext)
.ConfigureAwait(false);
}
} And then while configuring: services.AddMvc(...)
.AddOData((options, s) => {
...
options.AddRouteComponents("odata", s.GetRequiredService<IEdmModel>(), odataServiceCollection => {
...
odataServiceCollection.AddSingleton<IODataSerializerProvider, CustomODataSerializerProvider>();
odataServiceCollection.AddSingleton<GroupByODataResourceSetSerializer>();
});
}) This also returns the correct |
Enable write the apply result using OData payload
This old issue still is present in the latest AspNetCoreOData Version 8.2.3: OData/WebApi#1712
The text was updated successfully, but these errors were encountered: