I recently upgraded my .net project from .netcore3.1 to .net6 while also updating OData with its latest version (v8.0.11). The following code runs fine and returns correct OData response (context and value) and even the query filters work as expected.
[HttpGet]
[EnableQuery]
public IActionResult Get()
{
var persons = _db.Persons.AsQueryable();
return Ok(persons);
}
But when I try to convert this to PersonsDTO, it fails with error:
[HttpGet]
[EnableQuery]
public IActionResult Get()
{
var persons = _db.Persons.AsQueryable();
var response = persons.ProjectTo<PersonDTO>(_mapper.ConfigurationProvider);
return Ok(response);
}
ArgumentException: Object of type 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[ODataTest.Model.PersonDTO]' cannot be converted to type 'System.Linq.IQueryable`1[ODataTest.Model.Person]'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(StackAllocedArguments& stackArgs, ReadOnlySpan`1 parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.AspNetCore.OData.Query.ExpressionHelpers.OrderBy(IQueryable query, LambdaExpression orderByLambda, OrderByDirection direction, Type type, Boolean alreadyOrdered)
at Microsoft.AspNetCore.OData.Query.Expressions.BinderExtensions.ApplyBind(IOrderByBinder binder, IQueryable query, OrderByClause orderByClause, QueryBinderContext context, Boolean alreadyOrdered)
at Microsoft.AspNetCore.OData.Query.OrderByQueryOption.AddOrderByQueryForProperty(IOrderByBinder orderByBinder, OrderByClause orderbyClause, IQueryable querySoFar, QueryBinderContext binderContext, Boolean alreadyOrdered)
at Microsoft.AspNetCore.OData.Query.OrderByQueryOption.ApplyToCore(IQueryable query, ODataQuerySettings querySettings)
at Microsoft.AspNetCore.OData.Query.ODataQueryOptions.ApplyTo(IQueryable query, ODataQuerySettings querySettings)
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)
at Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.OnActionExecuted(ActionExecutedContext actionExecutedContext)
at Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- 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 Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Before I upgraded this .net and Odata it worked without issues but currently it throws the mentioned exception.
Here's my automapper configuration:
public PersonMapping()
{
CreateMap<Person, PersonDTO>()
.ForMember(dest => dest.PersonName,
opt => opt.MapFrom(
src => src.Name
));
}
and EDM Model:
IEdmModel GetEdmModel(){
var builder = new ODataConventionModelBuilder();
builder.EnableLowerCamelCase();
builder.EntitySet<Person>("Persons");
return builder.GetEdmModel();
}