Home > Software engineering >  An issue with AutoMapper in ASP.Net Core
An issue with AutoMapper in ASP.Net Core

Time:05-30

I have 2 classes to map:

public class Note
    {
        public Guid UserId { get; set; }
        public Guid Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
        public DateTime CreationDate { get; set; }
        public DateTime EditDate { get; set; }
    }
public class NoteDetailsVm : IMapWith<Note>
    {
        public Guid Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
        public DateTime CreationDate { get; set; }
        public DateTime EditDate { get; set; }

        public void Mapping(Profile profile)
        {
            profile.CreateMap<Note, NoteDetailsVm>();
        }
    }

Here is the mapping profile and the mapping interface:

public class AssemblyMappingProfile : Profile
    {
        public AssemblyMappingProfile(Assembly assembly) =>
            ApplyMappingsFromAssembly(assembly);

        private void ApplyMappingsFromAssembly(Assembly assembly)
        {
            var types = (from t in assembly.GetExportedTypes()
                        where t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapWith<>))  
                        select t).ToList();

            foreach (var type in types)
            {
                var instance = Activator.CreateInstance(type);
                var methodInfo = type.GetMethod("Mapping");
                methodInfo?.Invoke(instance, new object[] { this });
            }
        }
    }
public interface IMapWith<T>
    {
        void Mapping(Profile profile) =>
            profile.CreateMap(typeof(T), GetType());
    }

I use this method to handle requests and get the viewmodel:

public async Task<NoteDetailsVm> Handle(GetNoteDetailsQuery request, CancellationToken cancellationToken)
        {
            var entity = await _dbContext.Notes.FirstOrDefaultAsync(note => note.Id == request.Id, cancellationToken);

            if (entity == null || entity.UserId != request.UserId)
            {
                throw new NotFoundException(nameof(Note), request.Id);
            }

            return _mapper.Map<NoteDetailsVm>(entity);
        }

So when I run the tests, I get such error though I have the necessary mappings:

AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.

AutoMapper.AutoMapperMappingException
Missing type map configuration or unsupported mapping.

Mapping types:
Note -> NoteDetailsVm
Notes.Domain.Note -> Notes.Application.Notes.Queries.GetNoteDetails.NoteDetailsVm
   at lambda_method259(Closure , Object , NoteDetailsVm , ResolutionContext )
   at Notes.Application.Notes.Queries.GetNoteDetails.GetNoteDetailsQueryHandler.Handle(GetNoteDetailsQuery request, CancellationToken cancellationToken)

Why isn't the mapping working and how can I fix this?

CodePudding user response:

You most probably don't handle initialization in your tests. Check this guide here: https://www.thecodebuzz.com/unit-test-mock-automapper-asp-net-core-imapper/

The essence of it are these lines of code:

            if (_mapper == null)
            {
                var mappingConfig = new MapperConfiguration(mc =>
                {
                    mc.AddProfile(new SourceMappingProfile());
                });
                IMapper mapper = mappingConfig.CreateMapper();
                _mapper = mapper;
            }

They make sure there is an instance of the automapper that is properly initialized with the correct profile.

CodePudding user response:

Ok, I've managed to solve the problem, it had nothing to do with the code above. Just passed the wrong assembly to the profile constructor

  • Related