0
votes

I'm following this answer AutoMapper mapping int[] or List<int> from ViewModel to a List<Type> in Domain Model and have got it binding with my CategoryId to SelectedCategoryIds on UploadSongViewModel, however I want to also get it to bind SongId to Id on UploadSongViewModel.

namespace App
{
    public static class AutoMapper
    {
        public static MapperConfiguration Config;

        public static void Initialize()
        {
            //It works with CategoryId, but throws an error when I include SondId.
            Config = new MapperConfiguration(x =>
            {
                x.CreateMap<int, SongCategory>()
                    .IgnoreAllNonExisting()
                    .ForMember(dest => dest.CategoryId, opt => opt.MapFrom(src => src))
                    .ForMember(dest => dest.SongId, opt => opt.MapFrom(src => src)); //Code that's throwing exception

                x.CreateMap<UploadSongViewModel, Song>()
                    .IgnoreAllNonExisting()
                    .ForMember(dest => dest.AudioName, opt => opt.MapFrom(src => src.SongName))
                    .ForMember(dest => dest.AudioPath, opt => opt.MapFrom(src => src.SongPath))
                    .ForMember(dest => dest.SongCategories, opt => opt.MapFrom(src => src.SelectedCategoryIds))
                    .ForMember(dest => dest.SongCategories, opt => opt.MapFrom(src => src.Id)); //Code that's throwing exception
            });

            //Throws exception here because it can't bind SongId property
            Config.AssertConfigurationIsValid(); 
        }
    }
}

public abstract class Entity
{
    public int Id { get; set; }
}

public class SongCategory : Entity
{
    public int SongId { get; set; }
    public int CategoryId { get; set; }
}

public class Song : Audio
{
    public string AlbumName { get; set; }
    public string ArtistName { get; set; }

    public List<SongCategory> SongCategories { get; set;}
}

public class UploadSongViewModel
{
    public int Id { get; set; }
    public string ArtistName { get; set; }
    public string AlbumName { get; set; }
    public int[] SelectedCategoryIds { get; set; }

    public MultiSelectList CategoriesSelectList { get; set; }
}

I don't really understand what the auto mapper code is doing from Darin Dimitrov answer so it's hard to debug. If someone could explain how this mapping works for categoryId and why it is not working for SongId that would be great.

The exception I get is:

The following property on System.Collections.Generic.List1[[SoundVast.Models.SongCategory, SoundVast, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] cannot be mapped: SongCategories Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type System.Collections.Generic.List1[[SoundVast.Models.SongCategory, SoundVast, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]. Context: Mapping to property SongCategories from System.Int32 to System.Collections.Generic.List`1[[SoundVast.Models.SongCategory, SoundVast, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] Mapping from type SoundVast.Areas.Upload.Models.UploadSongViewModel to SoundVast.Models.Song Exception of type 'AutoMapper.AutoMapperConfigurationException' was thrown.

1

1 Answers

2
votes

This can be easily achieved with some custom mapping once the basic rules have been applied:

x.CreateMap<int, SongCategory>()
    .IgnoreAllNonExisting()
    .ForMember(dest => dest.CategoryId, opt => opt.MapFrom(src => src));

x.CreateMap<UploadSongViewModel, Song>()
    .IgnoreAllNonExisting()
    .ForMember(dest => dest.AudioName, opt => opt.MapFrom(src => src.SongName))
    .ForMember(dest => dest.AudioPath, opt => opt.MapFrom(src => src.SongPath))
    .ForMember(dest => dest.SongCategories, opt => opt.MapFrom(src => src.SelectedCategoryIds))
    .AfterMap((viewModel, model) => 
    {
        foreach (var item in model.SongCategories)
        {
            item.Id = viewModel.Id;
        }
    });