Search code examples
asp.net-core-mvcautomapping

Automapper in MVC Core 2.0 services.AddAutoMapper() behavior


I have a solution like this:

MVC Core 2.0 application <-> Business Class library <-> Domain class library
(ViewModel)    <- P1 ->      (Dto)         <-P2->       (Domain entity)

I created Automapper profiles in each MVC and Business projects for mapping ViewModel<->Dto (P1) and Dto<->Domain entity (P2). P1 profile&map is in MVC project, P2 profile&map is in Business library.

I then made a xUnit test project which creates a Dto object and sends it to a Business Service, inside the unit test on init I call:

Business.App.AutoMapperConfiguration.Configure();

And this unit test works exactly as expected.

I then do the same (I even copy/pasted code from Unit test) in the MVC controller and I get an error in mapping Dto to Domain entity:

Unmapped members were found. Review the types and members below...

I configured Automapper maps in startup.cs like this:

services.AddAutoMapper();

If I understand correctly this is supposed to traverse all assemblies for classes inheriting Profile and adding them to configuration.

Example map:

public class StrankaMap : Profile
{
    public override string ProfileName => nameof(StrankaMap);

    public StrankaMap()
    {
        CreateMap<SomeDto, SomeDomainEntity>().ReverseMap()
        CreateMap<AnotherDto, AnotherDomainEntity>().ReverseMap()
    }
}

I don't know what is the cause of this error if my unit test works but not from MVC app - I even copied the code from unit test to MVC controller and ran that. I'm suspecting an error in configuration. Do I assume correctly that inside Startup.cs adding services.AddAutoMapper(); is enough for this to work?

Solution (edit)

Apparently I misunderstood that the service.AddAutoMapper() will traverse all assemblies and search for Profile inherited classes. There might be a better solution but I used the one below, with the help of a hint from the comment @LucianBargaoanu.

I solved it like this:

// Startup.cs

services.AddAutoMapper(
    typeof(Business.App.AutoMapperConfiguration),
    typeof(MvcApp.Infrastructure.Configuration.AutoMapperConfiguration));


//And the AutoMapperConfiguration class:

namespace MvcApp.Infrastructure.Configuration
{
    using AutoMapper;

    public class AutoMapperConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(x =>
            {
                x.AddProfile<Models.Mapping.StrankaMap>();
            });
        }
    }
}

Solution

  • Apparently I misunderstood that the service.AddAutoMapper() will traverse all assemblies and search for Profile inherited classes. There might be a better solution but I used the one below, with the help of a hint from the comment @LucianBargaoanu.

    I solved it like this:

    // Startup.cs
    
    services.AddAutoMapper(
        typeof(Business.App.AutoMapperConfiguration),
        typeof(MvcApp.Infrastructure.Configuration.AutoMapperConfiguration));
    
    
    //And the AutoMapperConfiguration class:
    
    namespace MvcApp.Infrastructure.Configuration
    {
        using AutoMapper;
    
        public class AutoMapperConfiguration
        {
            public static void Configure()
            {
                Mapper.Initialize(x =>
                {
                    x.AddProfile<Models.Mapping.StrankaMap>();
                });
            }
        }
    }