I am writing a test OData Rest API with an InMemoryDatabase.
I would like to use DTO(s) to hide the SQL model and adjust a few fields (geographic positions and so on).
However, when I use ProjectTo<...>
method from AutoMapper, GET request to the API return an empty collection instead of the actual result list.
Do you have any idea about what I am doing wrong ?
Here is the controller :
namespace offers_api.Controllers
{
public class OffersController : ODataController
{
private readonly OfferContext _context;
private IMapper _mapper;
public OffersController(OfferContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
[EnableQuery]
public IActionResult Get()
{
IQueryable<Offer> res = _context.Offers.ProjectTo<Offer>(_mapper.ConfigurationProvider); // <-- works without ProjectTo !
return Ok(res);
}
}
}
The automapper declaration :
namespace offers_api.Entities
{
public class Mapping : Profile
{
public Mapping()
{
//CreateMap<CategoryEntity, string>().ConvertUsing(cat => cat.Name ?? string.Empty);
CreateMap<LocationEntity, Location>()
.ForMember(x => x.longitude, opt => opt.MapFrom(o => 0))
.ForMember(x => x.latitude, opt => opt.MapFrom(o => 0))
.ReverseMap();
CreateMap<OfferEntity, Offer>()
.ForMember(x => x.Category, opt => opt.MapFrom(o => o.Category.Name))
.ReverseMap()
.ForMember(x => x.Category, opt => opt.MapFrom(o => new CategoryEntity { Name = o.Category }));
CreateMap<OfferPictureEntity, OfferPicture>().ReverseMap();
CreateMap<UserEntity, User>().ReverseMap();
}
}
}
The EDM model :
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Offer>("Offers");
return builder.GetEdmModel();
}
I found the solution.
In fact, automapper loaded more data than OData's default behaviour. The relation between an offer and it's author was described by a non nullable foreing key. I didn't insert any author in the DB, but OData tried to load a user and saw it was missing in the USER table, so it discarded the Offer result.
Solution : make the foreign key nullable.
namespace offers_api.Entities
{
public class OfferEntity
{
[Key]
public long Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public long AuthorId { get; set; } // <== Bug here : add long? to resolve it...
public virtual UserEntity Author { get; set; }
}
}