Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automapper MapsTo Attribute does not work on referenced classes

I'm struggling to understand what I'm doing wrong here. I've been using Automapper + Automapper.Attributes (https://github.com/schneidenbach/AutoMapper.Attributes) in a solution and recently I've had to split my API project out into a "core" library and the original API. Automapper is not able to create a map when the class files are move outside of the API project. I have setup a demo project with the following structure to confirm this issue: (Available here: https://github.com/greghesom/AutoMapper_Example)

  • Solution
    • API (Customer and Person Class)
    • API.Core (Pet and Dog classes)

  • The API project references API.Core
  • The Pet class maps to the Dog class
  • The Person class maps to the Customer Class

API.Core - Dog Class

namespace API.Core
{
    public class Dog
    {
        public string Name { get; set; }
    }
}

API.Core - Pet Class

namespace API.Core
{
    [MapsTo(typeof(Dog))]
    public class Pet
    {
        [MapsToProperty(typeof(Dog), "Name")] //Edit: Fixed this typo
        public string PetName { get; set; }
    }
}

API - Person Class

namespace API.Models
{
    [MapsTo(typeof(Customer))]
    public class Person
    {
        [MapsToProperty(typeof(Customer), "FirstName")]
        public string Name { get; set; }
    }
}

API - Customer Class

namespace API.Models
{
    public class Customer
    {
        public string FirstName { get; set; }
    }
}

API - Startup

   AutoMapper.Mapper.Initialize(cfg => {
                typeof(API.WebApiConfig).Assembly.MapTypes(cfg);  
            });

API - Controller

var person = new Person { Name = "John" };
var customer = AutoMapper.Mapper.Map<Customer>(person);//This Works

var dog = new Dog { Name = "Lucky" };
var pet = AutoMapper.Mapper.Map<Pet>(dog);//This throws exception

EXCEPTION:

An error has occurred. Unmapped members were found. Review the types and members below. Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters ============================= AutoMapper created this type map for you, but your types cannot be mapped using the current configuration. Dog -> Pet (Destination member list) API.Core.Dog -> API.Core.Pet (Destination member list)

Unmapped properties: PetName AutoMapper.AutoMapperConfigurationException at lambda_method(Closure , Dog , Pet , ResolutionContext ) at lambda_method(Closure , Object , Object , ResolutionContext ) at API.Controllers.ValuesController.Get() in c:\users\greg\Source\Repos\AutoMapperTest\API\Controllers\ValuesController.cs:line 26 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()

like image 382
Greg Avatar asked Feb 17 '26 12:02

Greg


1 Answers

I ran into the same issue (AutoMapper 7.0.0). The key to the problem is in the error message: "AutoMapper created this type map for you, but your types cannot be mapped using the current configuration". From 6.2.0 onwards AutoMapper tries to create mappings itself for types that aren't explicitly mapped, ie: in a lot of cases it's no longer needed to create a mapping.

However, it seems that it's using the mappings it creates itself instead of your defined mappings, even for the types you explicitly defined them for. At least, that's what I ran into.

A quick way to check this: downgrade to version 6.1.1, and see if the problem still occurs. In my case, the downgrade solved the issue.

I do have a feeling there must be a better way to fix this (or maybe it's even a bug...), but I don't know how yet. In case I find it, I'll post back here. Just figured I'd thrown this out here already in case you need a quick fix :)

like image 54
Kevin Dockx Avatar answered Feb 20 '26 01:02

Kevin Dockx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!