Automapper: Extension method on null value not called anymore in MapFrom

Created on 17 Nov 2017  Â·  21Comments  Â·  Source: AutoMapper/AutoMapper

Source/destination types + Mapping configuration

CreateMap<Item, ItemDto>()
    .ForMember(d => d.Value, s => s.MapFrom(item => item.Value.SomeExtensionMethod()));

https://gist.github.com/DavidDeSloovere/694f23b10bd2c0d57316fcc76d60b084

Version: x.y.z

6.2.0 and 6.2.1

Expected behavior

Extension method gets called, like in 6.1.1

Actual behavior

Extension method is not called at all

Steps to reproduce

Run the gist with v6.1.1 and you'll get -1 for the value.
Run it with v6.2.0 and you'll get 0 for the value, which is the default and not the value from the extensionmethod.

Most helpful comment

Yes, we null check everything first.

All 21 comments

Yes, we null check everything first.

ResolveUsing doesn't null check. Check the execution plan.

So it's a breaking change in v6.2?
Did not see it in the release notes. Didn't expect a breaking change either in a minor version. So looked like a bug to me.

2276

IC.
Some switches in how this worked, but the current behaviour is the final one. Hope we'll find all the cases in all our projects.
Thanks.

The other option would be to make this configurable but the null check is
consistent with the BCL APIs.

On Mon, Nov 20, 2017 at 3:17 PM David De Sloovere notifications@github.com
wrote:

IC.
Some switches in how this worked, but the current behaviour is the final
one. Hope we'll find all the cases in all our projects.
Thanks.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/AutoMapper/AutoMapper/issues/2409#issuecomment-345834633,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAGYMj37-2wBlpZbGCpl5ftsW60dOpX6ks5s4exNgaJpZM4QiKJp
.

This affects us badly as well. We substitute an incoming null with an empty destination type object using MapFrom.

You can try NullSubstitute.

Since we don't know if your methods check for null or not, we assume not. Because we assume not, we'd rather not wrap every MapFrom in a "try...catch NullReferenceException", which is what we used to do. That's ugly.

Understood - makes sense. I think I saw those NullRef exceptions when cleared 'Enable Just My Code' in VS. Will think of something.
Thanks.

@lbargaoanu - thanks for advising, NullSubstitute worked.

Excuse my apparent ignorance, but I've been struggling with this for a while now, and I think I don't understand how the different option methods work.

Initially I had
.ForMember(x => x.Weight, opt => opt.MapFrom(s => (s.Metric != null) ? s.Metric.Weight : s.Component.Weight))

As you can see, my source object has two different properties from which I draw to map to a flattened object. To reduce complexity I wanted to replace this with

.ForMember(x => x.Weight, opt => opt.MapFrom(s => s.Metric.GetValueOrAlt(v => v.Weight, s.Component.Weight)))

But with this change in your component, the extension method is not called when s.Metric is null.
I also can't use NullSubstitute here because that doesn't give me access to s through an Expression<Func<TSource, TSourceMember>> parameter. What is your suggested solution?

Replacing MapFrom with ResolveUsing will work. The latter will run the expression even if Metric is null.

.ForMember(x => x.Weight, opt => opt.ResolveUsing(s => s.Metric.GetValueOrAlt(v => v.Weight, s.Component.Weight)))

_Aside from that:_
Personally I would use the null-coalescing operator ?? and write something like this. Just for a simples syntax.

.ForMember(x => x.Weight, opt => opt.ResolveUsing(s => s.Metric?.Weight ?? s.Component.Weight))

Thanks for the reply.

Now that ResolveUsing has been remove in v8, what's the recommended pattern here if source value is null? A custom ValueConverter?
In my gist, the extensionmethod could be converted to a ValueConverter.

If you just want to have a specific value in case of null, the NullSubstitute can work, but I don't see how you can specify extra options.

Just the name changed.

Do you mean than the originel MapFrom has been removed and the implementation of ResolveUsing is the new MapFrom?

I did. That why I came back to this issue. But it's still unclear to me. I think MapFrom is still not executing when the value is null.

I don't know, maybe smth is missing in the docs. They are all called MapFrom now. But the Func based ones work like ResolveUsing, as opposed to the Expression based ones, which work like the old MapFrom. If that helps, feel free to add smth to the docs, as they are supposed to explain things.

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

Hamidnch picture Hamidnch  Â·  3Comments

Mds92 picture Mds92  Â·  5Comments

vadimshaporov picture vadimshaporov  Â·  7Comments

dmdymov picture dmdymov  Â·  3Comments

gmarokov picture gmarokov  Â·  6Comments