mctuna
mctuna

Reputation: 871

AutoMapper ForMember and MapFrom is not executed

ForMember/MapFrom is somehow not executed whatever I try.

Those are the classes to be mapped;

    public class ImageParams : IEntityParams, IImage, IOperatorFields
{
    public ImageParams()
    {

    }

    public ImageParams(string userId, string title, string description, string imagePath, bool profilePhoto)
    {
        UserId = userId;
        Title = title;
        Description = description;
        ImagePath = imagePath;
        ProfilePhoto = profilePhoto;
    }

    public ImageParams(int id, string userId, string title, string description, string imagePath, bool profilePhoto)
    {
        Id = id;
        UserId = userId;
        Title = title;
        Description = description;
        ImagePath = imagePath;
        ProfilePhoto = profilePhoto;
    }

    [JsonProperty(PropertyName = "id")]
    public int Id { get; set; }
    [JsonProperty(PropertyName = "userId")]
    public string UserId { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    [JsonProperty(PropertyName = "imagePath")]
    public string ImagePath { get; set; }
    [JsonProperty(PropertyName = "profilePhoto")]
    public bool ProfilePhoto { get; set; }
    public Status Status { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? LastModifiedDate { get; set; }
}
public interface IImage: IEntity, IHasStatus, IDateOperationFields
{
    string UserId { get; set; }
    string Title { get; set; }
    string Description { get; set; }
    string ImagePath { get; set; }
    bool ProfilePhoto { get; set; }
}
public class Image: IImage
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public string Title { get; set; }        
    public string Description { get; set; }
    public string ImagePath { get; set; }
    public bool ProfilePhoto { get; set; }
    public Status Status { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime? LastModifiedDate { get; set; }
    public ApplicationUser ApplicationUser { get; set; }
    public List<ReportImage> Reports { get; set; }
    public List<Report> UserReports { get; set; }
}

I create the map as below;

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Image, ImageParams>().ForMember(x => x.ImagePath, o => o.MapFrom(s => ImagePathFormatting(s.ImagePath))).ReverseMap();
    }

    private static string ImagePathFormatting(string imagePath)
    {
        var formattedImagePath = imagePath.Contains(AppSettingsProvider.PictureBaseUrl) ? imagePath : $"{AppSettingsProvider.PictureBaseUrl}/{imagePath}";
        return formattedImagePath;
    }
 }

I register my profile as below;

services.AddAutoMapper(typeof(MappingProfile));

And I try to map as below;

public ImageParams GetProfileImage(string userId)
    {
        var image = Entities.FirstOrDefault(x => x.UserId == userId && x.ProfilePhoto && x.Status == Status.Active);
        
        return _mapper.Map<ImageParams>(image);
    }

I am sure the MappingProfile is executed successfully and mapping Image object to ImageParams object as well however ImagePathFormatting function is not called.

I have tried so many variations like instead of ImagePathFormatting I have used anonymous funtion. I have also tried using IValueResolver as below;

    public class CustomResolver : IValueResolver<ImageParams, Image, string>
{
    public string Resolve(ImageParams source, Image destination, string imagePath, ResolutionContext context)
    {
        return source.ImagePath.Contains(AppSettingsProvider.PictureBaseUrl) ? source.ImagePath : $"{AppSettingsProvider.PictureBaseUrl}/{source.ImagePath}";
    }
}

Whatever I try, I cannot make MapFrom nor CustomResolver invoked. Any help would be appreciated.

Upvotes: 0

Views: 1046

Answers (2)

Michael Wiles
Michael Wiles

Reputation: 21194

I'd strongly suggest you use AutoMapper Execution Plan Tool tool to see exactly what automapper is doing when it runs the mapping.

Confident that will solve your problem.

Upvotes: 2

Maxim
Maxim

Reputation: 869

First solution: Remove from class ImageParams any constructor except default without parameters:

public class ImageParams : IImage
    {
        public ImageParams()
        {

        }
    //Other members.
    }

Second solution: Add DisableConstructorMapping():

var config = new MapperConfiguration(cfg => {
                    cfg.AddProfile(new MappingProfile());
                    cfg.DisableConstructorMapping();
                }
            );
var mapper = config.CreateMapper();

Third solution:

CreateMap<ImageParams, Image>()
                .ForMember(x => x.ImagePath, o => o.MapFrom(s => ImagePathFormatting(s.ImagePath)))
                .ReverseMap()
                .ForMember(x => x.ImagePath, o => o.MapFrom(s => ImagePathFormatting(s.ImagePath)))
                .ConstructUsing(x => new ImageParams());

Source 1 Source 2

Upvotes: 3

Related Questions