costa costa - 1 month ago 69
C# Question

Why do I get "Missing type map configuration or unsupported mapping" error in automapper?

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;

namespace TestAutomapper
{
class Program
{
static void Main(string[] args)
{

var config = new MapperConfiguration(cfg => cfg.CreateMap<MyClassSource, MyClassDestination>());


var mapper = config.CreateMapper();

var source = new MyClassSource { DateTimeValue = null };

var mapped = mapper.Map<MyClassSource, MyClassDestination>(source);
}

}

public class MyClassSource
{
public object DateTimeValue { get; set; }
}

public class MyClassDestination
{
public DateTime? DateTimeValue { get; set; }
}
}


The error is:

AutoMapper.AutoMapperMappingException was unhandled
HResult=-2146233088
Message=Error mapping types.

Mapping types:
MyClassSource -> MyClassDestination
TestAutomapper.MyClassSource -> TestAutomapper.MyClassDestination

Type Map configuration:
MyClassSource -> MyClassDestination
TestAutomapper.MyClassSource -> TestAutomapper.MyClassDestination

Property:
DateTimeValue
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at lambda_method(Closure , MyClassSource , MyClassDestination , ResolutionContext )
at TestAutomapper.Program.Main(String[] args) in C:\Users\costa\documents\visual studio 2015\Projects\TestAutomapper\TestAutomapper\Program.cs:line 22
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
HResult=-2146233088
Message=Missing type map configuration or unsupported mapping.

Mapping types:
Object -> Nullable`1
System.Object -> System.Nullable`1[[System.DateTime, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at lambda_method(Closure , Object , Nullable`1 , ResolutionContext )
at lambda_method(Closure , MyClassSource , MyClassDestination , ResolutionContext )
InnerException:


I thought this error was solved (https://github.com/AutoMapper/AutoMapper/issues/1095). I am using Automapper 5.1.1.

How do I fix this?

Thanks

Edit: Just to clarify, I am concerned with the handling of the null value. I understand that converting from a non-null object value to DateTime is complicated. In the real code, the actual value in the source object is null or DateTime. I thought the null is handled without errors.

Edit:

I created an extension method ToDate to convert an object to a date and I added this mapping to handle conversions from object to DateTime?:

cfg.CreateMap<object, DateTime?>().ConstructUsing(src => src.ToDate());

Answer

As the properties in your source and destination types have the same name, AutoMapper will try to convert from object to DateTime? which is not possible, and that's why you're getting the error you mentioned.

You need to define how you want to resolve the DateTime? property. This will work:

var config = new MapperConfiguration(
    cfg =>
    {
        cfg.CreateMap<MyClassSource, MyClassDestination>()
            .ForMember(
                destination => destination.DateTimeValue,
                memberOptions => memberOptions.ResolveUsing(sourceMember =>
                {
                    DateTime dateTime;
                    return !DateTime.TryParse(sourceMember.DateTimeValue.ToString(), out dateTime) ? (DateTime?) null : dateTime;
                }));
    }
);

If your source member is a valid date time object, it'll be converted to date time, otherwise the destination property will get a null value.