Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper error saying mapper not initialized

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.

like image 972
si2030 Avatar asked Dec 22 '16 13:12

si2030


People also ask

Why you should not use AutoMapper?

1. If you use the convention-based mapping and a property is later renamed that becomes a runtime error and a common source of annoying bugs. 2. If you don't use convention-based mapping (ie you explicitly map each property) then you are just using automapper to do your projection, which is unnecessary complexity.

What to do when mapper is not initialized?

Mapper not initialized. Call Initialize with appropriate configuration #2951 After upgrading to v8 if get this error. I have read the upgrade doc but still nothing works. InvalidOperationException: Mapper not initialized. Call Initialize with appropriate configuration.

Why can't I use MAPPER in a container?

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. I think this is better suited for StackOverflow.

Is it possible to get the static API for automapper?

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 Show activity on this post. Thanks for contributing an answer to Stack Overflow!

How to use MAPPER instance instead of static mapper?

Instead of using static Mapper.Map method, you need to use mapper instance created via configuration, like following: var mapper = cfg.CreateMapper (); var company = (Company)mapper.Map (companyFormViewModel, company, typeof (CompanyFormViewModel), typeof (Company));


1 Answers

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.

like image 105
Chris Pratt Avatar answered Sep 30 '22 06:09

Chris Pratt