I'm trying to implement an API using OData with DTOs using .NET 5.0
[EnableQuery]
public IActionResult Get(ODataQueryOptions<BookDto> options)
{
...
var books = this._db.Books.ProjectTo<BookDto>();
return Ok(books);
}
Note here, the "options" parameter is there only so I can check the expand statements (which is excluded for brevity), and use explicit expansion, otherwise, I rely on the [EnableQuery] attribute to apply the query.
My EDM model contains the DTOs, instead of the entities, like this:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<BookDto>("Books");
builder.EntitySet<PressDto>("Presses");
return builder.GetEdmModel();
The BookDto contains a navigation prop to PressDto:
public class BookDto
{
public int Id { get; set; }
... other props
public PressDto Press { get; set; }
}
public class PressDto
{
public int Id { get; set; }
public string Name { get; set; }
public Category Category { get; set; }
public PersonDto Owner { get; set; }
}
This way, the $expands work pretty well, however $select inside expand throws an exception:
- /odata/books?$expand=Press -> this works fine
- /odata/books?$expand=Press($expand=Owner) -> this works fine
- /odata/books?$select=Title -> this works fine
- /odata/books?$expand=Press($select=Category) -> this throws an exception
System.InvalidOperationException: Rewriting child expression from type 'ODataPoc.Models.Category' to type 'System.Nullable`1[ODataPoc.Models.Category]' is not allowed, because it would change the meaning of the operation. If this is intentional, override 'VisitUnary' and change it to allow this rewrite.at System.Linq.Expressions.ExpressionVisitor.ValidateChildType(Type before, Type after, String methodName)at System.Linq.Expressions.ExpressionVisitor.ValidateUnary(UnaryExpression before, UnaryExpression after)at Microsoft.EntityFrameworkCore.Query.Internal.QueryOptimizingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
If I use entities instead of DTOs, and no ProjectTo, it works fine. So something is off with the ProjectTo, I just can't figure out what. If possible, I'd like to use DTOs so any help is much appreciated.