2

I´m trying to use Automapper with Dependency Injection configuration on a n-layer application.

 public class ApplicationMapping : Profile
{
    public ApplicationMapping()
    {
        RegisterMappings();
        Mapper.AssertConfigurationIsValid();
    }  

    private void RegisterMappings()
    {
      CreateMap<IEnumerable<App>, ListAppsDto>()
            .ForMember(dest => dest.Apps,
                       opt => opt.MapFrom(src =>
                            Mapper.Map<IEnumerable<App>, List<App>>(src.ToList())
                           )
                      );
    }
}

This class is inside my Application dll, where I put my services and DTOs. Also in this dll, I have an extension method to register the mapping:

 public static class MappingServiceExtension
{
    public static void AddApplicationMappings(this IServiceCollection services)
    {
        var mapperConfig = new MapperConfiguration(config =>
        {
            config.AddProfile<ApplicationMapping>();
        });

        IMapper mapper = mapperConfig.CreateMapper();
        services.AddSingleton(mapper);
    }
}

Then in my WebAPI project, on the Startup.cs class I put:

  services.AddApplicationMappings();

And I use it normally with DI in my services:

  public class AppService : IAppService
 {
    private readonly IAppRepository _appRepository;
    private readonly IMapper _mapper;

    public TruckService(IAppRepository appRepository, IMapper mapper)
    {
        _appRepository = appRepository;
        _mapper = mapper;
    }
 }

I would like to use like this. But I'm getting an exception when the Mapper.AssertConfigurationIsValid(); line runs, saying that:

'Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.'

What am I missing here? The problem seems to be in the Mapper.Map<IEnumerable<App>, List<App>>(src.ToList()) line of code.

But how can I get an instance of the Mapper there without using the static Mapper?

2
  • You need Custom type converter for IEnumerable<App>, List<App> and take mapper from ResolutionContext. Commented May 20, 2019 at 20:58
  • It not resolved the problem because I still need to use the context.Mapper.Map<...> on the CustomTypeConverter class. Still getting the same error. Commented May 20, 2019 at 21:08

3 Answers 3

2
Mapper.AssertConfigurationIsValid();

This calls the static IMapper instance which is used in situations where you don’t use dependency injection. Since you never set up the static mapper, using it there will fail.

What you want to do instead is call AssertConfigurationIsValid on the actual mapper instance, the one that you are registering as a singleton. So you should remove the assert from the mapper profile and instead call it within your AddApplicationMappings method:

IMapper mapper = mapperConfig.CreateMapper();
mapper.AssertConfigurationIsValid();
services.AddSingleton(mapper);
Sign up to request clarification or add additional context in comments.

1 Comment

2

Try using AddAutoMapper from AutoMapper.Extensions.Microsoft.DependencyInjection which you can add as a NuGet package.

So, you'd completely remove the MappingServiceExtension class, and then in Startup.cs add these two lines:

AutoMapper.Mapper.Reset();
services.AddAutoMapper(typeof(ApplicationMapping).Assembly);

I forgot the exact reason, but when using AutoMapper in across multiple projects/assemblies, you need to register it for DI this way. Read more here.

1 Comment

You don’t need the AutoMapper.Extensions.Microsoft.DependencyInjection if you prefer to use an explicit mapping configuration as OP does. The package is mostly useful for auto-discovery of mapping profiles.
0

Similar to what @johnluke.laue suggested. In AddApplicationMappings simply replace the code with the following:

services.AddAutoMapper(config =>
{
    config.AddProfile<ApplicationMapping>();
});

The above will automatically add the IMapper to the DI. In addition, modify the RegisterMappings function as below. You don't need to explicitly map the IEnumerable<T>. It will be mapped implicitly if the source/destination mappings exist.

private void RegisterMappings()
{
   CreateMap<IEnumerable<App>, ListAppsDto>()
       .ForMember(dest => dest.Apps, opt => opt.MapFrom(src => src.ToList());
}

It would be helpful to see the actual App and ListAppDto classes, as you don't explicitly need the above mappings. I hope this helps

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.