I'm trying to map a DTO to a Type. I did already did it the other way around.
The tricky part is getting the Many-to-Many
relationship right.
Where Book
has an ICollection<BookCategory>
the BookDTO
has an ICollection<int>
.
namespace Core.Entities
{
public class Book : IAggregateRoot
{
public int BookId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string CoverImageUrl { get; set; }
public string Layout { get; set; }
public ICollection<Chapter> Chapters { get; set; }
public ICollection<BookCategory> BookCategories { get; set; }
public ICollection<BookTag> BookTags { get; set; }
}
}
namespace API.DTOs
{
public class BookDTO : DTO
{
public int BookId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string CoverImageUrl { get; set; }
public string Layout { get; set; }
public ICollection<int> Categories { get; set; }
public ICollection<int> Tags { get; set; }
}
}
namespace Core.Entities
{
public class BookCategory : IAggregateRoot
{
public int BookId { get; set; }
public Book Book { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
}
In my MappingProfile I have this code:
namespace API
{
public class MappingProfile : Profile
{
public MappingProfile()
{
// Entity -> DTO
// src being the concrete type T in CreateMap<T, DTO>()
CreateMap<Book, BookDTO>()
.ForMember(dto => dto.Categories, options => options.MapFrom(src => src.BookCategories.Select(bc => bc.CategoryId).ToList()))
.ForMember(dto => dto.Tags, options => options.MapFrom(src => src.BookTags.Select(bt => bt.TagId).ToList()));
...
// DTO -> Enitity
CreateMap<BookDTO, Book>()
.ForMember(
book => book.BookCategories,
options => options.ConvertUsing(dto => dto.Categories.Select(category => new BookCategory
{
BookId = dto.BookId,
CategoryId = category
}).ToList()));
...
// The simplified version
CreateMap<List<int>, List<BookCategory>>().ConstructUsing(listOfInts => listOfInts.Select(singleInt => new BookCategory {
BookId = singleInt,
CategoryId = singleInt
}).ToList());
}
// An external conversion function
// Usage:
// ConvertUsing(dto => ConvertBookDtoToList(dto))
private ICollection<BookCategory> ConvertBookDtoToList(BookDTO dto)
{
return dto.Categories.Select(category => new BookCategory {
BookId = dto.BookId,
CategoryId = category
}).ToList();
}
}
}
However using any of these approaches results in an error:
Severity Code Description Project File Line Suppression State
Error CS0411 The type arguments for method 'IMemberConfigurationExpression<BookDTO, Book, object>.ConvertUsing<TValueConverter, TSourceMember>(Expression<Func<BookDTO, TSourceMember>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. API C:\Users\pebes\source\repos\ip6_uiux-ereader-app\book_designer\API\MappingProfile.cs 40 Active
I don't really understand the error message, as would appear to me to make sense.
How can I resolve this?
CodePudding user response:
CovertUsing is using for another purpose and it must be after CreateMap. It`s using to set up another way to convert one value to another
Instead of ConvertUsing you must use MapFrom, which do what you want:
CreateMap<BookDTO, Book>()
.ForMember(
book => book.BookCategories,
options => options.MapFrom(dto =>
dto.Categories.Select(category => new BookCategory
{
BookId = dto.BookId,
CategoryId = category
}).ToList()
)
);