Saad Farooq
Saad Farooq

Reputation: 997

AutoMapper: Keep Destination Value if the property doesnt exists in source

I tried to search a lot, and try different options but nothing seems to work.

I am using ASP.net Identity 2.0 and I have UpdateProfileViewModel . When Updating the User info, I want to map the UpdateProfileViewModel to ApplicationUser (i.e. the Identity Model); but I want to keep the values, I got from the db for the user. i.e. the Username & Email address, that doesn't needs to change.

I tried doing :

Mapper.CreateMap<UpdateProfileViewModel, ApplicationUser>()
.ForMember(dest => dest.Email, opt => opt.Ignore());

but I still get the Email as null after mapping:

var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
user = Mapper.Map<UpdateProfileViewModel, ApplicationUser>(model);

I also tried this but doesn't works:

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    {
        var sourceType = typeof(TSource);
        var destinationType = typeof(TDestination);
        var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
        foreach (var property in existingMaps.GetUnmappedPropertyNames())
        {
            expression.ForMember(property, opt => opt.Ignore());
        }
        return expression;
    }

and then:

 Mapper.CreateMap<UpdateProfileViewModel, ApplicationUser>()
.IgnoreAllNonExisting();

Upvotes: 3

Views: 6108

Answers (3)

manu
manu

Reputation: 1

Do :

Mapper.Map(model, user);

instead of :

user = Mapper.Map<UpdateProfileViewModel, ApplicationUser>(model);

Upvotes: 0

Aldo Pestoy
Aldo Pestoy

Reputation: 11

Mapper will return a new object when assigned to the destination object, instead you must use Map to pass the source and destination as parameters.

public class SourceObjectModel 
{
    public string Name { get; set; }
}

public class DestinationObjectModel
{
    public int Id { get; set; }
    public string Name { get; set; }
}

SourceObjectModel sourceObj = new SourceObjectModel() {Name = "foo"};
DestinationObjectModel destinObj = new DestinationObjectModel(){Id = 1};


/*update only "name" in destinObj*/
_mapper.Map<SourceObjectModel, DestinationObjectModel>(sourceObj, destinObj);

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038850

All you need is to create a mapping between your source and destination types:

Mapper.CreateMap<UpdateProfileViewModel, ApplicationUser>();

and then perform the mapping:

UpdateProfileViewModel viewModel = ... this comes from your view, probably bound
ApplicationUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
Mapper.Map(viewModel, user);

// at this stage the user domain model will only have the properties present
// in the view model updated. All the other properties will remain unchanged
// You could now go ahead and persist the updated 'user' domain model in your
// datastore

Upvotes: 8

Related Questions