Skip null values with custom resolver

Solution 1:

UPDATE: IsSourceValueNull is not available starting from V5.

If you want all source properties with null values to be ignored you could use:

Mapper.CreateMap<SourceType, DestinationType>()
  .ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull));

Otherwise, you can do something similar for each member.

Read this.

Solution 2:

For newer versions that utilize the Instance API, use this instead:

var mappingConfig = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Condition(
        (source, destination, sourceMember, destMember) => (sourceMember != null)));
});

Note: This functionality works as of 5.0.2, breaking on later versions as of this writing. Waiting for the next 5.2.x release is recommended if upgrading from 5.0.2.

Solution 3:

The solution here works for my project, which is using AutoMapper 6.0.2. In previous projects using AutoMapper 4, I had used IsSourceValueNull to achieve similar behavior. I have nullable types mapped to non-nullable types in my project, this solution is able to handle that scenario.

I made a small change to the original solution. Instead of checking the type of the property to be mapped, I set the filter in ForAllPropertyMaps to check the type of the source object, so that the custom resolver only applies to maps from that source object. But the filter can be set to anything as needed.

var config = new MapperConfiguration(cfg =>
{
    cfg.ForAllPropertyMaps(
        pm => pm.TypeMap.SourceType == typeof(<class of source object>),
        (pm, c) => c.ResolveUsing<object, object, object, object>(new IgnoreNullResolver(), pm.SourceMember.Name));
});

class IgnoreNullResolver : IMemberValueResolver<object, object, object, object>
{
    public object Resolve(object source, object destination, object sourceMember, object destinationMember, ResolutionContext context)
    {
        return sourceMember ?? destinationMember;
    }
}

Solution 4:

I've got the same exact issue with mapping up the conditionals to the non-generic types. Here's how I solved it.

Wire up:

foreach (PropertyInfo p in type.GetProperties().Where(x => x.GetCustomAttributes<SkipMapIfNullAttribute>().Any()))
    map.ForMember(p.Name, x => x.ResolveUsing(typeof(SkipMapIfNullResolver)).FromMember(p.Name));

The second .FromMember is required so the value for the member is passed to the value resolver, rather than the full model.

The resolver looks like this:

public class SkipMapIfNullResolver : IValueResolver
{
    public ResolutionResult Resolve(ResolutionResult source)
    {
        if (source.Value == null)
            source.ShouldIgnore = true;

        return source;
    }
}