It is long.
So, I have a model and a view model that I am updating from an AJAX request. The Web API controller receives a view model, which then updates the existing model using AutoMapper, as shown below:
private User updateUser(UserViewModel entityVm) { User existingEntity = db.Users.Find(entityVm.Id); db.Entry(existingEntity).Collection(x => x.UserPreferences).Load(); Mapper.Map<UserViewModel, User>(entityVm, existingEntity); db.Entry(existingEntity).State = EntityState.Modified; try { db.SaveChanges(); } catch { throw new DbUpdateException(); } return existingEntity; }
I have an automapper configured this way to display User -> UserViewModel (and vice versa).
Mapper.CreateMap<User, UserViewModel>().ReverseMap();
(Note that explicitly setting the opposite display and throwing a ReverseMap exhibits the same behavior)
I am having a problem with a Model / ViewModel member, which is an ICollection of another object:
[DataContract] public class UserViewModel { ... [DataMember] public virtual ICollection<UserPreferenceViewModel> UserPreferences { get; set; } }
The corresponding model is as follows:
public class User { ... public virtual ICollection<UserPreference> UserPreferences { get; set; } }
Problem:
Each property of the User and UserViewModel classes correctly displays, with the exception of ICollections UserPreferences / UserPreferenceViewModels, shown above. When these collections are displayed from the ViewModel in the Model, and not from the map properties, a new instance of the UserPreference object is created from the ViewModel, rather than updating the existing object using the ViewModel properties.
Model:
public class UserPreference { [Key] public int Id { get; set; } public DateTime DateCreated { get; set; } [ForeignKey("CreatedBy")] public int? CreatedBy_Id { get; set; } public User CreatedBy { get; set; } [ForeignKey("User")] public int User_Id { get; set; } public User User { get; set; } [MaxLength(50)] public string Key { get; set; } public string Value { get; set; } }
And the corresponding ViewModel
public class UserPreferenceViewModel { [DataMember] public int Id { get; set; } [DataMember] [MaxLength(50)] public string Key { get; set; } [DataMember] public string Value { get; set; } }
And the automapper configuration:
Mapper.CreateMap<UserPreference, UserPreferenceViewModel>().ReverseMap();
When mapping a UserViewModel to a user, ICollection of UserPreferenceViewModels also displays the user ICollection UserPreferences, as you would expect.
However, when this happens, individual properties of the UserPreference object, such as "DateCreated", "CreatedBy_Id", and "User_Id", are reset to zero, as if creating a new object, not individual copies that are being copied.
This is also shown as evidence that when matching a UserViewModel that has only 1 UserPreference object in the collection, when checking the DbContext after the map operator, there are two local UserPreference objects. One that looks like a new object created using the ViewModel, and one that is the original of the existing model.
How can I make automapper update existing elements of the Model collection rather than instantiate new members from the ViewModel collection? What am I doing wrong here?
Screenshots for demonstration before / after Mapper.Map ()

