Mapper not initialized, When Use ProjectTo()
Asked Answered
C

2

19

I Use Automapper 5.2.0 In My Project. When I Use ProjectTo() In Code Get This Error:

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.

Service Code

 public async Task<FreelancerProfileViewModel> GetFreelancerProfile()
    {
        var id = Guid.Parse(_identity.GetUserId());
        var model = await _freelancerProfiles
            .AsNoTracking()
            .Where(_ => _.User.Id == id)
            .ProjectTo<FreelancerProfileViewModel>()
            .FirstAsync();

     //  var viewmodel =  _mapper.Map<FreelancerProfileViewModel>(model);

        return model;
    }

Automapper Profile

   public class FreelancerDashbordProfile : Profile
{
    private readonly IIdentity _identity;
    public FreelancerDashbordProfile(IIdentity identity)
    {
        _identity = identity;
        var id = Guid.Parse(_identity.GetUserId());
        CreateMap<FreelancerProfile, FreelancerProfileViewModel>()
        .ForMember(_ => _.DoingProjectCount,
            __ => __.MapFrom(_ => _.Projects.Count(project => project.ProjectState == ProjectState.Doing)))

        .ForMember(_ => _.EndProjectCount,
            __ => __.MapFrom(_ => _.Projects.Count(project => project.ProjectState == ProjectState.End)))

        .ForMember(_ => _.ProjectCount, __ => __.MapFrom(_ => _.Projects.Count));

    }

}

Also I Use StructureMap For IoC

AutoMapperRegistery

   public AutoMapperRegistery()
    {

        this.Scan(scan =>
        {
            scan.TheCallingAssembly();
            scan.AssemblyContainingType<SkillProfile>(); // for other asms, if any.
            scan.WithDefaultConventions();

            scan.AddAllTypesOf<Profile>().NameBy(item => item.FullName);
        });

        this.For<MapperConfiguration>().Singleton().Use("MapperConfig", ctx =>
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMissingTypeMaps = true; // It will connect `Person` & `PersonViewModel` automatically.
                addAllCustomAutoMapperProfiles(ctx, cfg);
            });
            config.AssertConfigurationIsValid();

            return config;
        });

        this.For<IMapper>()
            .Singleton()
            .Use(ctx => ctx.GetInstance<MapperConfiguration>().CreateMapper(ctx.GetInstance));


    }

I See Other Question and Issue but not solved my problem.

Cynde answered 31/1, 2017 at 15:35 Comment(0)
S
31

You need to pass the MappingConfiguration provider to the ProjectTo call.

public async Task<FreelancerProfileViewModel> GetFreelancerProfile()
{
    var id = Guid.Parse(_identity.GetUserId());
    var model = await _freelancerProfiles
        .AsNoTracking()
        .Where(_ => _.User.Id == id)
        .ProjectTo<FreelancerProfileViewModel>(_mapper.Configuration)
        .FirstAsync();

 //  var viewmodel =  _mapper.Map<FreelancerProfileViewModel>(model);

    return model;
}
Sarisarid answered 31/1, 2017 at 15:41 Comment(3)
Is there any possible way to pass configuration provider to all mappings? I think this is not a good solution. Do I have to pass config file to my all queries? I didn't find any better solution by the way :/Cythiacyto
If are you looking for unit test case as mentioned at #47482434 in the Mapper.Initialize for dotnet core 2.x+ add type Startup like services.AddAutoMapper(typeof(Startup))Pablopabon
@Cythiacyto I don't think there is a "native" way with AutoMapper, but you could write a very simple Extension Method which wraps the ProjectTo<>() call and injects the _mapper.Configuration reference every time it is called.Myriammyriameter
G
20

In the .NET Core 3.1 (AutoMapper 9.0.0) new registration is: services.AddAutoMapper(typeof(Startup));

In the .NET Core 2.1 (AutoMapper 7.0.1) version you have to pass the ConfigurationProvider.

  1. Register AutoMapper like described here

  2. Inject to the Controller:

    private readonly IMapper _mapper; public SomeController(ApplicationDbContext dbContext, IMapper mapper) { _mapper = mapper; }

  3. Pass the ConfigurationProvider this way:

    ApplicationDbContext.SomeEntities.ProjectTo(_mapper.ConfigurationProvider)

Geoff answered 10/9, 2018 at 6:34 Comment(5)
This case is about ASP.NET MVC 5.X ( full framework no .net core ). anyway, thanks to announcing.Cynde
There are no any mentions about it above. So let's leave it genericGeoff
Is there a way to wire it up in a static extension method ?Ambulant
Thanks, this worked for ProjectTo, but is there a way to get Mapper.Map() to work?Marten
Mapper.Map is old approach and it's obsolete. New approach - inject the IMapper to the target type. Not sure if they still support the first one. Try to find the docsGeoff

© 2022 - 2024 — McMap. All rights reserved.