25

I am using Automapper 5.2. I have used as a basis this link. I will describe, in steps, the process of setting up Automapper that I went through.

First I added Automapper to Project.json as indicated:

PM> Install-Package AutoMapper

Second I created a folder to hold all files relating to mapping called "Mappings"

Third I set up the configuration of Automapper in its own file in the mappings folder :

public class AutoMapperConfiguration
{
    public MapperConfiguration Configure()
    {
        var config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile<ViewModelToDomainMappingProfile>();
            cfg.AddProfile<DomainToViewModelMappingProfile>();
            cfg.AddProfile<BiDirectionalViewModelDomain>();
        });
        return config;
    }
}

Forth Also in its own file in the mappings folder I set up the mapping profile as follows:

public class DomainToViewModelMappingProfile : Profile
{
    public DomainToViewModelMappingProfile()
    {
        CreateMap<Client, ClientViewModel>()
           .ForMember(vm => vm.Creator, map => map.MapFrom(s => s.Creator.Username))
           .ForMember(vm => vm.Jobs, map => map.MapFrom(s => s.Jobs.Select(a => a.ClientId)));
    }
}

Fifth, I added an extension method as its own file also in the mappings folder... this was used next in startup.cs:

public static class CustomMvcServiceCollectionExtensions
{
    public static void AddAutoMapper(this IServiceCollection services)
    {
        if (services == null)
        {
            throw new ArgumentNullException(nameof(services));
        }
        var config = new AutoMapperConfiguration().Configure();
        services.AddSingleton<IMapper>(sp => config.CreateMapper());
    }
}

Sixth I added this line into the ConfigureServices method in Startup.cs

        // Automapper Configuration
        services.AddAutoMapper();

Finally I used it in a controller to convert a collection...

 IEnumerable<ClientViewModel> _clientVM = Mapper.Map<IEnumerable<Client>, IEnumerable<ClientViewModel>>(_clients);

Based on the question I referred to earlier I thought I had everything set so I could use it however I got an error on the line above in the Controller...

"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 have I missed.. Is this the correct way to set up Automapper? I suspect I am missing a step here.. any help greatly appreciated.

Community
  • 1
  • 1
si2030
  • 3,895
  • 8
  • 38
  • 87
  • 3
    Hi.. Did you find the solution? Am also facing the same issue. – Praveen May 04 '17 at 06:41
  • I'm getting this error with AutoMapper.Extensions.Microsfot.DependencyInjection Version 5.0.1 and AutoMapper 7.0.1. Installing 3.2.0 with AutoMapper 6.1.1 fixed the issue and let's me call _mapper.Map normally. I don't know why cause as far as I can tell I'm not calling the static Mapper class and I'm not using ProjectTo or UseAsDataSource. – MDave Sep 22 '18 at 21:50

4 Answers4

39

AutoMapper has two usages: dependency injection and the older static for backwards compatibility. You're configuring it for dependency injection, but then attempting to use the static. That's your issue. You just need to choose one method or the other and go with that.

If you want to do it with dependency injection, your controller should take the mapper as a constructor argument saving it to a member, and then you'll need to use that member to do your mapping:

public class FooController : Controller
{
    private readonly IMapper mapper;

    public FooController(IMapper mapper)
    {
        this.mapper = mapper;
    }

Then:

IEnumerable<ClientViewModel> _clientVM = mapper.Map<IEnumerable<Client>, IEnumerable<ClientViewModel>>(_clients);

For the static method, you need to initialize AutoMapper with your config:

public MapperConfiguration Configure()
{
    AutoMapper.Mapper.Initialize(cfg =>
    {
        cfg.AddProfile<ViewModelToDomainMappingProfile>();
        cfg.AddProfile<DomainToViewModelMappingProfile>();
        cfg.AddProfile<BiDirectionalViewModelDomain>();
    });
}

You then need only call this method in Startup.cs; you would no longer register the singleton.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • Static way is no longer available with latest version https://automapper.readthedocs.io/en/latest/Setup.html – ErTR Apr 28 '20 at 00:21
  • @Chris could you please look into this one https://stackoverflow.com/questions/73744463/automapper-upgrade-to-6-1-0-assertconfigurationisvalid-fails-in-servicestack – A_m0 Sep 16 '22 at 15:54
0

Starting with V9.0 of autoMapper, the static API is no longer available. or you can change version to 6.2.2 from NuGet Package Manager See this doc confgiration AutoMapper

0

I had the same problem. Automapper was working fine on my pc. When i deployed it was not working because i missed System.ValueTupple.dll .

Santosh P
  • 125
  • 1
  • 3
-3

Better Solution would be to create extension method like this

  public static DestinationType CastObject<SourceType, DestinationType>(this SourceType obj)
            {
                var config = new MapperConfiguration(cfg =>
                cfg.CreateMap<SourceType, DestinationType>());

                var mapper = config.CreateMapper();

                var entity = mapper.Map<DestinationType>(obj);

                return entity;
            }
  • @LucianBargaoanu , what is the problem with this, automapper static fucntion not working, is this solution wrong or cannot work , would you explain ? – Syed Rizwan ul Haq Apr 21 '19 at 15:30
  • 2
    @SyedRizwanulHaq, the bad is that AM configuration is defined each time you invoke the method. – Chris W Jul 24 '19 at 05:31