Attempting to perform a query using Marten Queryable, ASP.NET OData 8 and Newtonsoft for ASP .NET and seeing the following exception:
System.NotSupportedException: Marten does not know how to use result type System.Collections.IEnumerable
at Marten.Internal.Storage.DocumentStorage`2.BuildHandler[TResult](IMartenSession session, ISqlFragment statement, ISqlFragment currentStatement)
at Marten.Linq.Parsing.LinqQueryParser.buildHandlerForCurrentStatement[TResult](Statement top, SelectorStatement selector)
at Marten.Linq.Parsing.LinqQueryParser.BuildHandler[TResult]()
at Marten.Linq.MartenLinqQueryProvider.Execute[TResult](Expression expression)
at Marten.Linq.MartenLinqQueryable`1.System.Collections.IEnumerable.GetEnumerator()
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)
at Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Formatters.NewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|22_0(ResourceInvoker invoker, IActionResult result)
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)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Prometheus.HttpMetrics.HttpRequestDurationMiddleware.Invoke(HttpContext context)
at Prometheus.HttpMetrics.HttpRequestCountMiddleware.Invoke(HttpContext context)
at Prometheus.HttpMetrics.HttpInProgressMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
It looks like Newtonsoft tries to iterate over the IQueryable implementation using the non-generic iterator. It calls MartenLinqQueryable.GetEnumerator() which results in the BuildHandler throwing an exception on this line because TResult is a non-generic IEnumerable without a type parameter matching TDocument.
Sample of the controller:
using Api.Data;
using Api.Model;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
namespace Buyside.OrdersAndTrades.Api.Controllers;
[Authorize]
[Route("/rest/v0/orders")]
public sealed class OrderController(IOrderRepository orderRepository) : ODataController
{
[HttpGet]
[EnableQuery]
public IQueryable<Order> GetAllOrders()
{
return orderRepository.GetAllOrders();
}
}
Sample of the repository:
using Api.Model;
using Api.Queries;
using Marten;
namespace Buyside.OrdersAndTrades.Api.Data;
public class OrderRepository(IDocumentStore store) : IOrderRepository
{
private readonly IDocumentStore _store = store;
public IQueryable<Order> GetAllOrders()
{
using var session = CreateSession();
return session.Query<Order>();
}
private IDocumentSession CreateSession() => _store.LightweightSession();
}
Marten 7.9.0:
Attempting to perform a query using Marten Queryable, ASP.NET OData 8 and Newtonsoft for ASP .NET and seeing the following exception:
It looks like Newtonsoft tries to iterate over the IQueryable implementation using the non-generic iterator. It calls MartenLinqQueryable.GetEnumerator() which results in the BuildHandler throwing an exception on this line because TResult is a non-generic IEnumerable without a type parameter matching TDocument.
Sample of the controller:
Sample of the repository:
Sample of setup for OData and Newtonsoft: