DonO
DonO

Reputation: 1070

How to ignore mapping source null values globally?

Is there a way to ignore mapping null values to destination globally (for all mapping configurations)?

Something that goes in here:

    //Automapper config
    Mapper.Initialize(cfg =>
    {
        //Initializes all mapping profiles in the assembly
        cfg.AddProfiles(Assembly.GetExecutingAssembly().GetName().Name);

        //If map is called without a profile creates default map
        cfg.CreateMissingTypeMaps = true;
    });

This is for instance mapping. Here is one example of what i'm trying to accomplish.

//Models
    class User {
      public string Name {get; set;}
      public string Email {get; set;}
      public string Password {get; set;}
    }

    class UserDto {
      public string Name {get; set;}
      public string Email {get; set;}
    }

//Start instances
     var user = new User { Name = "John", Email = "[email protected]", Password = "123"};

     var userDto = new UserDto { Name = "Tim" };
//Notice that we left the Email null on the DTO


//Mapping
    Mapper.Map(userDto, user);

The result ends up with the user having a null email. I want the user email to not be changed unless a new email is provided on the source (userDto). In other words ignore all null properties of all types on the source object from overwriting destination (User)

UPDATE: None of the answers below solve the problem. They simply do not work for collections. While the Autommaper figures out this bug I was able to get around my problem by using an ExpandoObject to filter out all null properties before mapping as below:

var patchInput = new ExpandoObject() as IDictionary<string, object>;

foreach (var property in userDto.GetType().GetProperties())
    if (property.GetValue(userDto) is var propertyValue && propertyValue != null)
        patchInput.Add(property.Name, propertyValue);

Mapper.Map(patchInput, user);

Upvotes: 2

Views: 967

Answers (1)

Valerii
Valerii

Reputation: 2317

It should work

Mapper.Initialize(cfg =>
        {
            cfg.AddProfiles(Assembly.GetExecutingAssembly().GetName().Name);
            cfg.CreateMissingTypeMaps = true;
            cfg.ForAllMaps((typeMap, map) =>
                map.ForAllMembers(option => option.Condition((source, destination, sourceMember) => sourceMember != null)));
        });

Upvotes: 1

Related Questions