'AutoMapper - Trying to flatten my object property to string but getting an error

I am trying to map my ProductDto to Product class. I get an error when mapping the string property in ProductDto class to a Brand property in the Product class.

AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
ProductDto -> Product
SilksyAPI.Dto.ProductDto -> SilksyAPI.Entities.Product

Type Map configuration:
ProductDto -> Product
SilksyAPI.Dto.ProductDto -> SilksyAPI.Entities.Product

Destination Member:
Brand

 ---> AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.

Mapping types:
String -> Brand
System.String -> SilksyAPI.Entities.Brand

Here is my mapping profile:

CreateMap<Product, ProductDto>()
    .ForMember(dest => dest.Brand, opt => opt.MapFrom(p => p.Brand.Name))
    .ForMember(dest => dest.Categories, opt => opt.MapFrom(p => p.ProductCategories.Select(pc => pc.Category.Name)));

CreateMap<ProductDto, Product>()
    .ForMember(dest => dest.Brand, opt => opt.MapFrom(src => src.Name));

Classes:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }

    public int BrandId { get; set; }
    public Brand Brand { get; set; }

    public ICollection<ProductCategory> ProductCategories { get; set; }
}
public class Brand
{
    public int Id { get; set; }

    [Required]
    [MaxLength(100)]
    public string Name { get; set; }
}

Dto Class

 public class ProductDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public string Brand { get; set; }
    public List<string> Categories { get; set; }

}

I have tried different mapping profiles but I cannot map from ProductDto to Product but can map from Product to ProductDto with no problem.

Here are a few other things I tried

CreateMap<Brand, string>()
    .IncludeMembers(b => b.Name);


CreateMap<Product, ProductDto>()
    .ForMember(dest => dest.Brand, opt => opt.MapFrom(p => p.Brand.Name))
    .ForMember(dest => dest.Categories, opt => opt.MapFrom(p => p.ProductCategories.Select(pc => pc.Category.Name)))
    .ReverseMap();

And

Mapper.CreateMap<Brand, string>().ConvertUsing(source => source.Name ?? string.Empty);

https://docs.automapper.org/en/stable/Flattening.html



Solution 1:[1]

From your first mapping profile, when mapping from ProductDto to Product, for Brand property, you need to create a new Brand instance as below:

cfg.CreateMap<ProductDto, Product>()
   .ForMember(dest => dest.Brand, opt => opt.MapFrom(src => new Brand { Name = src.Name }));

Sample Program


For .IncludeMembers()

I don't think it suits your scenario as you are mapping from object to string but not object to object.


For .ConvertUsing()

You need to add the code below to mapping from string to Brand for Brand property.

cfg.CreateMap<string, Brand>()
   .ConvertUsing(source => new Brand { Name = source });

Sample program (.ConvertUsing())

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yong Shun