I am trying to expose a simple data model using an WebAPI OData service. My data is stored in a database which I am accessing using EF. Because the tables in my DB use different property names and there are too many fields which are needed in my DTO's, I use AutoMapper to map (or rather, ProjectTo
) from DB objects to DTO's.
DTO's are as follows:
public class OrderDTO
{
[Key]
public int SalesOrderNumber { get; set; }
//Navigation
public virtual IEnumerable<OrderLineDTO> OrderLines { get; set; }
}
public class OrderLineDTO
{
[Key]
[ForeignKey("Order")]
public int SalesOrderNumber { get; set; }
[Key]
public int LineNumber { get; set; }
//Navigation
public virtual OrderDTO Order { get; set; }
}
When I access a specific order I get my repsonse as expected (ie: the requested order):
http://localhost/.../Orders(salesOrderNumber=1)
When trying to expand the orderLines property using following request I get the below response:
http://localhost/.../Orders(salesOrderNumber=1)?$expand=orderLines
{
"@odata.context": "http://localhost/.../$metadata#Orders/$entity",
"division": "STAND",
"salesOrderNumber": 1,
"orderLines@odata.context": "http://localhost/.../$metadata#Orders(salesOrderNumber=1)/orderLines",
"orderLines": []
}
I suspect the reason my orderLines object is empty is because AutoMapper doesn't take the expand into consideration when converting from DB objects to DTO's. My entity query looks like this:
_dbContext.ORDERS
.Include("LINES")
.Where(o => (o.ORD_NUM == salesOrderNumber))
.ProjectTo<OrderDTO>()
.FirstOrDefault();
AutoMapper has mappings for both OrderDTO and OrderLineDTO. Configured as follows:
CreateMap<ORDERS, OrderDTO>()
.ForMember(dest => dest.SalesOrderNumber, opt => opt.MapFrom(src => src.ORD_NUM));
CreateMap<LINES, OrderLineDTO>()
.ForMember(dest => dest.SalesOrderNumber, opt => opt.MapFrom(src => src.ORD_NUM))
.ForMember(dest => dest.LineNumber, opt => opt.MapFrom(src => src.LIJNNR));
It seems to me that this should be enough to be able to $expand
into my orderLines but I can't get this to work. What am I missing here?
It really seems to me you are missing explicit configuration for mapping ORDERS.LINES to OrderDto.OrderLines
:
CreateMap<ORDERS, OrderDTO>()
.ForMember(dest => dest.OrderLines, opt => opt.MapFrom(src => src.LINES))
.ForMember(dest => dest.SalesOrderNumber, opt => opt.MapFrom(src => src.ORD_NUM));