David Reing
David Reing

Reputation: 40

Automapper attempts to create object when map returns null

When I try to do some custom mapping and sometimes map a destination property to null, Automapper throws an exception trying to create the destination property object.

I've uploaded a simplified project to github to demonstrate: https://github.com/dreing1130/AutoMapper_Investigation

This began when I upgraded from Automapper 6 to 8.

If I return a newed up object instead of null it works fine (my application is expecting that value to be null in these cases though)

I also confirmed that a breakpoint inside my map is hit each time the mapping is called to make sure there wasn't a compiled execution plan

public class Source
{
    public IEnumerable<string> DropDownValues { get; set; }
    public string SelectedValue { get; set; }
}

public class Destination
{
    public SelectList DropDown { get; set; }
}

CreateMap<Source, Destination>()
        .ForMember(d => d.DropDown, o => o.MapFrom((src, d) =>
        {
            return src.DropDownValues != null
                ? new SelectList(src.DropDownValues,
                    src.SelectedValue)
                : null;
        }));

Expected Result: Destination.DropDown is null when Source.DropdownValues is null

Actual Result: An Exception is thrown

"System.Web.Mvc.SelectList needs to have a constructor with 0 args or only optional args.Parameter name: type"

Upvotes: 0

Views: 1283

Answers (1)

devNull
devNull

Reputation: 4219

You can use a PreCondition here, which will avoid mapping (and even trying to resolve the source value) if the specified condition is not met:

CreateMap<Source, Destination>()
    .ForMember(d => d.DropDown, o =>
    {
        o.PreCondition(src => src.DropDownValues != null);
        o.MapFrom((src, d) =>
        {
            return new SelectList(src.DropDownValues, src.SelectedValue);
        });
    });

The reason for needing this is explained here:

For each property mapping, AutoMapper attempts to resolve the destination value before evaluating the condition. So it needs to be able to do that without throwing an exception even if the condition will prevent the resulting value from being used.

Upvotes: 3

Related Questions