WebApi
WebApi copied to clipboard
$apply=aggregate returns only JSON payload
$apply=aggregate returns only JSON payload in response without ODATA annotations for unbound function. There is no ODATA headers in response as well.
Request: $apply=aggregate(Id with sum as IdSum)
Response Body: [{"IdSum":6}]
Response Headers: Content-Type: application/json; charset=utf-8 Date: Fri, 14 Dec 2018 09:53:26 GMT Server: Kestrel Transfer-Encoding: chunked
Assemblies affected
Microsoft.AspNetCore.OData 7.1.0
Reproduce steps
Create unbound function like this [HttpGet] [EnableQuery] [ODataRoute(nameof(GetAddress))] public IActionResult GetAddress()
Get EDM model: var builder = new ODataConventionModelBuilder(); builder.ComplexType < Address > (); builder.Function(nameof(AddressController.GetAddress)).ReturnsCollection < Address > (); return builder.GetEdmModel();
Model: public class Address { public int Id { get; set; } }
Expected result
{"@odata.context":"http://localhost:12345/odata/$metadata#Collection(WebApiClassic.Address)","value":[{"@odata.id":null,"IdSum":6}]}
Actual result
[{"IdSum":6}]
Additional detail
It looks like Microsoft.AspNet.OData.Formatter.Serialization.DefaultODataSerializerProvider.GetODataPayloadSerializerImpl(Type type, Func<IEdmModel> modelFunction, ODataPath path, Type errorType) can't find proper serializer for type {System.Linq.EnumerableQuery`1[Microsoft.AspNet.OData.Query.Expressions.NoGroupByAggregationWrapper]}.
I use the following code to make it works: builder.ComplexType< Microsoft.AspNet.OData.Query.Expressions.DynamicTypeWrapper >();
Now it returns: {"@odata.context":""http://localhost:12345/odata/$metadata#Collection(Microsoft.AspNet.OData.Query.Expressions.DynamicTypeWrapper)","value":[{"@odata.id":null,"IdSum":6}]}
@kosinsky Do you have any idea about this?
Are you deriving controller form ODataController or adding [ODataFormatting] attribute explicitly? Without ODataFormatting serialization fallbacks to basic Asp .Net
Are you deriving controller form ODataController or adding [ODataFormatting] attribute explicitly? Without ODataFormatting serialization fallbacks to basic Asp .Net
I inherit my controller from ODataController:
public class AddressController : ODataController
Code:
public class Program
{
public static void Main(string[] args)
{
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build().Run();
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddOData();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc(b =>
{
b.Select().Expand().Filter().OrderBy().MaxTop(100).Count();
b.MapODataServiceRoute("odata", "odata", GetEdmModel());
});
}
private static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.ComplexType<Address>();
builder.Function(nameof(AddressController.GetAddress)).ReturnsCollection<Address>();
return builder.GetEdmModel();
}
}
public class AddressController : ODataController
{
[HttpGet]
[EnableQuery(MaxOrderByNodeCount = 32)]
[ODataRoute(nameof(GetAddress))]
public IActionResult GetAddress()
{
return Ok(new List<Address>
{
new Address { Id = 1 },
new Address { Id = 2 },
new Address { Id = 3 }
});
}
}
public class Address
{
public int Id { get; set; }
}
I did some digging. Looks like it reproduces only for .NET Core and for cases when controller returns IActionResult. It worked properly when I modified GetAddress() method to look like:
public IQueryable<Address> GetAddress()
{
return new List<Address>
{
new Address { Id = 1 },
new Address { Id = 2 },
new Address { Id = 3 }
}.AsQueryable();
}
I'll continue investigation
I did some digging. Looks like it reproduces only for .NET Core and for cases when controller returns IActionResult. It worked properly when I modified GetAddress() method to look like:
public IQueryable<Address> GetAddress() { return new List<Address> { new Address { Id = 1 }, new Address { Id = 2 }, new Address { Id = 3 } }.AsQueryable(); }
I'll continue investigation
It works with with IQueryable. Thank you.
https://github.com/OData/WebApi/issues/1712#issuecomment-451596881 if I need return badrequest in this function, what shall I do?
This is still an issue in the latest AspNetCoreOData Version
I faced the same issue, this is how I solved it in my application: https://github.com/peterkovecses/ODataApplyDemo