I have tried this answer: automapper multi objects to one object. However, my second mapping mapper.Map(additionalUploadSongViewModel, songs);
is still overwriting the other fields with default values, it is mapping BuyLink
and Lyrics
correctly though.
namespace App
{
public static class AutoMapper
{
public static MapperConfiguration Config;
public static void Initialize()
{
//Removed other mappings for verbose
Config = new MapperConfiguration(x => {
x.CreateMap<UploadSongViewModel, Song>()
.IgnoreAllNonExisting()
.ForMember(a => a.AudioName, m => m.MapFrom(s => s.SongName))
.ForMember(a => a.AudioPath, m => m.MapFrom(s => s.SongPath));
x.CreateMap<AdditionalUploadSongViewModel, Song>()
.IgnoreAllNonExisting();
});
//No errors here
Config.AssertConfigurationIsValid();
}
}
}
IgnoreAllNonExisting()
is just an extension method that should ignore properties that aren't set in both models, I thought this would fix the problem but it hasn't.
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
foreach (var property in expression.TypeMap.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
Domain Models:
public abstract class Entity
{
public int Id { get; set; }
}
public abstract class Audio : Entity
{
public string AudioName { get; set; }
public string AudioPath { get; set; }
public string CoverImagePath { get; set; }
}
public class Song : Audio
{
//Removed some for verbose
public string AlbumName { get; set; }
public string ArtistName { get; set; }
public string Lyrics { get; set; }
public string BuyLink { get; set; }
}
ViewModels:
public class UploadSongViewModel
{
public int Id { get; set; }
public string SongName { get; set; }
public string ArtistName { get; set; }
public string AlbumName { get; set; }
public string SongPath { get; set; }
public string CoverImagePath { get; set; }
}
public class AdditionalUploadSongViewModel
{
public string BuyLink { get; set; }
public string Lyrics { get; set; }
}
Controller:
[HttpPost]
public async Task<ActionResult> UploadMusic(IList<UploadSongViewModel> uploadSongsViewModel, IList<AdditionalUploadSongViewModel> additionalUploadSongViewModel)
{
//uploadSongViewModel and additionalUploadSongViewModel has all properties filled out properly here.
IMapper mapper = AutoMapper.Config.CreateMapper();
List<Song> songs = mapper.Map<List<UploadSongViewModel>, List<Song> (uploadSongsViewModel.ToList());
//songs now have proper mapped properties from uploadSongsViewModel
mapper.Map(additionalUploadSongViewModel, songs);
//all songs properties (songName, artistName etc) have now been overwritten by additionalUploadSongViewModel properties, instead of only BuyLink and Lyrics.
}