Automapper: Bug in using Include to map derived classes

Created on 6 May 2019  路  10Comments  路  Source: AutoMapper/AutoMapper

Source/destination types

public class Destination 
{
   public string Field { get; set; }
}

public class Source
{
}

public class DerivedSource : Source
{
}

Mapping configuration

CreateMap<DerivedSource, Destination>();

CreateMap<Source, Destination>()
  .Include<DerivedSource, Destination>()
  .ForMember(dest => dest.Field, opts => opts.Ignore());

Version: 8.1.0

Expected behavior

In AutoMapper 6.2.2, mapping inheritance worked regardless of ordering of CreateMap calls. However, after upgrading to version 8 we have to make sure that any derived types are declared after the base class which Includes these same base types. The above example fails (AssertConfigurationIsValid in the MapperConfiguration throws an AutoMapperConfigurationException) because Include<DerivedSource, Destination>() is done _after_ CreateMap<DerivedSource, Destination>(). If the maps are created in opposite order (i.e. do CreateMap<Source, Destination>() first) the mapping works as intended.
Interestingly, ordering does not appear to be relevant when using IncludeBase . This seems to indicate that this is a bug with Include, and not an intentional (breaking) change with version 8?

Actual behavior

AutoMapper.AutoMapperConfigurationException :
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
DerivedSource -> Destination (Destination member list)

Unmapped properties:
Field3

Steps to reproduce

// Your calls to Mapper.Map or ProjectTo here, with source/destination objects constructed
Bug

Most helpful comment

Thanks. That looks like a bug indeed.

All 10 comments

Are you missing anything in your configuration? From the mapping it looks like AssertConfigurationIsValid should fail, for both mappings. For the base mapping, you have one extra property, and for the derived mapping, the names don't match.

Please note, I tried to boil the example code down to the bare minimum. I hope the types/classes/fields are not too confusing. If possible, please disregard the types and fields; my point is there seems to be some issue with the ordering of the CreateMap calls. In our project, the mapping broke after upgrading to AutoMapper 8, and we fixed it by simply moving the CreateMap which includes the derived types to the top -- above the CreateMap's for the derived types.

A repro would help. Make a gist that we can execute and see fail. The example above is not useful.

I hope this gist is a more helpful example: https://gist.github.com/joakimgk/db0980309dfe2cecd20b759170c6f4da
As I tried explaining, the problem seems to be that the order the maps are created matters -- this was not the case before upgrading to version 8.

That works. Without a failing test, there is nothing we can do about it.

Hi again! Sorry for the incomplete test case. We have updated the gist with a more thorough example, which we are confident encapsulates the problem: https://gist.github.com/joakimgk/db0980309dfe2cecd20b759170c6f4da

Thanks. That looks like a bug indeed.

Hi there, I just wanted to add that all my profiles which have IncludeAllDerived() now fail to actually include the base properties in the derived mappings - this happened after upgrading to 8.1.0 while it worked fine in 8.0.0. Seems like it may be related.

Try the branch in the PR. If that doesn't work, a repro would help. Make a gist that we can execute and see fail.

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