Automapper: Version 4.2.1.0 : Problem with ProjectTo

Created on 9 Apr 2016  路  9Comments  路  Source: AutoMapper/AutoMapper

I am using AutoMapper 4.2.1.0 to map an entity type into a DTO using ProjectTo .

I have created my Map like this :

var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Order, OrderDTO>();
                cfg.CreateMap<Order_Detail, Order_DetailDTO>();
            });

and I am using config object like this :

var builder = config.ExpressionBuilder;
return ((IQueryable<Order>) property.GetValue(_db, null)).ProjectTo<OrderDTO>(builder);

but I am getting an error that says :

Missing map from Order to OrderDTO. Create using Mapper.CreateMap.

Is there something that I do wrong ?

Here is the same question that I asked on SO:
http://stackoverflow.com/questions/36450885/automapper-doesnt-work-as-it-should

Most helpful comment

var ((IQueryable<TEntity>) property.GetValue(_db, null)).ProjectTo<TDto>(config); should work

All 9 comments

var ((IQueryable<TEntity>) property.GetValue(_db, null)).ProjectTo<TDto>(config); should work

Interesting, I found that this ONLY works if you give the ProjectTo(obj) call specifically an instance of a MapperConfiguration, I would expect that given the new approach this should work with an IMapperConfiguration or IMapper too.

Also IMapperConfiguration appears to be missing the method "CreateMapper" is that by design?

@TehWardy There's another overload to pass IMapperConfiguration and only that. The static API is back so you use a static instance you don't have to pass over IMapperConfiguration.

And yes CreateMapper no longer shows up in Static or IMapperConfiguration by design. Creating maps at any point in time after initialization causes issues with order and map inheritance, so you have to do them all at once.

When I do this I get an exception ...

There's another overload to pass IMapperConfiguration and only that.

This makes sense but it's not what i'm trying to do ...

Creating maps at any point in time after initialization causes issues with order and map inheritance

For example:

In my situation I am using Ninject as my IoC container in to the object that has the various methods I want to call. In this case my methods are various CRUD operations on an IQueryable set from my DB layer below this code.

now lets assume I have the following ...

A ninject module:

    public class AutoMapperNinjectModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IMapperConfiguration>().ToMethod(k => new MapperConfiguration(cfg =>
            {
                var profiles = TypeHelper.GetWebStackAssemblies()
                    .SelectMany(a => a.GetTypes())
                    .Where(t => t.BaseType == typeof(Profile))
                    .ToList();

                profiles.ForEach(p => cfg.AddProfile(Activator.CreateInstance(p, null) as Profile));
            })).InSingletonScope();

            Bind<IMapper>().ToMethod(k => ((MapperConfiguration)k.Kernel.Get<IMapperConfiguration>()).CreateMapper()).InSingletonScope();
        }
    }

And then in my class I pass these in as Ctor args ...

IMapper mapper;
IMapperConfiguration mapperConfig;

When querying the db ...

var result = db.GetAll().ProjectTo<TDto>(mapperConfig);

... this for me this does not work without casting mapperConfig to the concrete type "MapperConfiguration" first.
I also cannot give the same ProjectTo call the IMapper I have for some reason (i would prefer to only ever pass around an IMapper instance).

In a creation scenario I appear to be getting similar problems, for example ...

var mappedDto = mapper.Map<TEntity>(data);
var savedEntity = await service.AddAsync(mappedDto);
var result = mapper.Map<TDto>(savedEntity);

... this for me has been picked up as a testing fail by my QA team, and upon further testing I can confirm the same problem.
Whereas the same init code used with a static mapper works fine.

Do I have use different overloads with the new non static versions to what I was using with the old static versions?

The IMapper vs IMapperConfiguration for ProjectTo was @jbogard code. I thought it was confusing too.

There shouldn't be any special overrides other than what's defined in the documentation. I'm not familiar with NInject, so I don't know if that might be the problem.

My suggestion is if you can, go back to the static implementation using

Mapper.Initialize(cfg =>
            {
                var profiles = TypeHelper.GetWebStackAssemblies()
                    .SelectMany(a => a.GetTypes())
                    .Where(t => t.BaseType == typeof(Profile))
                    .ToList();

                profiles.ForEach(p => cfg.AddProfile(Activator.CreateInstance(p, null) as Profile));
            });

and just call Mapper.Map

Ok looking at the tests defined here:

https://github.com/AutoMapper/AutoMapper/tree/da4dde57d2ee8fbf5b9d850333fc5354010edfc4/src/UnitTests/Projection

It looks like projectTo also supports passing a MapperConfiguration param to it to use with the Projection.

In testing I managed to get this to behave :)

thx @jbogard

@jbogard It's probably worth noting that for "good coding practice" the API mentioned in my last comment should probably accept a IMapperConfig or an IMapper instead if that's possible instead of requiring the concrete types ... it would likely promote better forward compatibility.

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