Automapper: Conditions do not get either Source or Destination values

Created on 19 Aug 2016  路  8Comments  路  Source: AutoMapper/AutoMapper

For the given code:
map.ForAllMembers(source => { source.Condition((src, dest, srcVal, destVal) => { if (srcVal == null) return !(destVal == null); return !srcVal.Equals(destVal); }); });

"srcVal" and "destVal" are always the default value for their respective property. I am therefore unable to do conditional mappings using this "ForAllMembers" context as i have no concrete way of being able to retrieve and compare what my Source and Destination values are.
automapper issue

Note: I have walked through this including when it is for the "Colour" property. Both srcVal and destVal are the default for that type (it is a struct, so all internal values are default 0)

Bug

All 8 comments

For the source property value, there was a bug that I fixed, but the destination property value seemed ok to me. So if you still have issues after the PR is merged, report back with details.

Legendary. Thanks!

I came across this issue and created a test case for it.

This fails with 5.1.1:

using System;
using Should;
using Xunit;

namespace AutoMapper.UnitTests.Bug
{
    public class AllMembersNotNullBug
    {
        public class Rule
        {
            public string ApplicationName { get; set; }

            public string CreatedBy { get; set; }
            public DateTime CreatedDate { get; set; }
            public string CurrencyCode { get; set; }
            public int GroupId { get; set; }
        }

        [Fact]
        public void Should_map_all_null_values_to_its_substitute()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Rule, Rule>()
                    .ForAllMembers(opt => opt.Condition((src, dest, srcVal, destVal, c) =>
                    {
                        return srcVal != null;
                    }));
            });

            var source = new Rule
            {
                ApplicationName = "Chain42ApplicationName",
                CreatedBy = null,
                CreatedDate = new DateTime(),
                CurrencyCode = null,
                GroupId = 42
            };

            var destination = new Rule
            {
                ApplicationName = "CommonApplicationName",
                CreatedBy = null,
                CreatedDate = new DateTime(),
                CurrencyCode = "CommonCurrencyCode",
                GroupId = 1
            };

            config.CreateMapper().Map(source, destination);

            destination.GroupId.ShouldEqual(42); // OK
            destination.ApplicationName.ShouldEqual("Chain42ApplicationName"); // ERROR

        }
    }
}

To get around it I used a custom resolver.

Hi @vascofernandes can you provide the custom resolver you used, by chance? I am definitely running into this problem as well and have spent a good portion of the day trying to figure out WTF is going on. :stuck_out_tongue: Any assistance/guidance you can provide this newb would be greatly appreciated!

Reverting to 5.0.2.0 also seems to fix this problem, too. :+1: _whew_

For my very particular case I was able to solve it like so, because only one specific property of my mapping was causing me a problem:

    public class SystemRuleNotNullProfile : Profile
    {
        public SystemRuleNotNullProfile()
        {
            CreateMap<SystemRule, SystemRule>()
                .ForMember(t => t.ApplicationName, opt => opt.ResolveUsing<ApplicationNameResolver>())
                .ForAllOtherMembers(opt => opt.Condition((src, dest, srcVal, destVal, c) =>
                {
                    return srcVal != null;
                }))
                //.ForAllMembers(opt => opt.Condition((src, dest, srcVal, destVal, c) => {
                //    return srcVal != null;
                //}))
                ;
        }
    }


    public class ApplicationNameResolver : IValueResolver<SystemRule, SystemRule, string>
    {
        public string Resolve(SystemRule source, SystemRule destination, string destMember, ResolutionContext context)
        {
            if (source.ApplicationName != null)
            {
                return source.ApplicationName;
            }

            return destination.ApplicationName;
        }
    }

Another possibility could be to try something like this for all the properties that matter to you.


            CreateMap<A, B>()
                .ForMember(t => t.Prop1, opt => opt.Condition((src, dest, srcVal, destVal, c) =>
                {
                    return src.Prop1 != null;
                }))

Awesome, thanks for your help, @vascofernandes. 5.0.2.0 reversion has fixed me for now, but this is definitely good to know/see from a knowledge transfer/feature-set perspective.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

colin-young picture colin-young  路  6Comments

jepl4052 picture jepl4052  路  6Comments

dmdymov picture dmdymov  路  3Comments

majidsoltani picture majidsoltani  路  5Comments

Hamidnch picture Hamidnch  路  3Comments