3

I've been messing with AutoMapper for a few days now, but I am having the most difficult time mapping values for what to me seems like basic tasks. I'm most likely the dumb one, but it's starting to get really frustrating with all these constant exceptions being thrown. /rant

Anyway, I have an Entity Framework proxy object Company. Through a base class Entity it has a property called CreatedDateTime which is a DateTime. I also have a DTO object called CompanyDto, which has a property called CreatedDateTime which is a string. All I want to do is take the DateTime value and flatten it to ToString("g"). I've tried a bunch of things, all of which throw an exception of some kind. The only mapping that has worked is, surprise, surprise: .Ignore(). Here's my latest attempt with a TypeConverter:

Mapper.CreateMap<DateTime, string>().ConvertUsing<DateTimeToStringConverter>();

public sealed class DateTimeToStringConverter : TypeConverter<DateTime, string> {
    protected override string ConvertCore(
        DateTime source) {
        if (source != null) {
            return source.ToString("g");
        }

        return string.Empty;
    }
}

And that causes this: Type 'System.String' does not have a default constructor

Jimmy, you browsing SO? Point me in the right direction please because at this point I think I'll get more work done by manually mapping than with AutoMapper.

Oh, this is with AutoMapper 3.1.1, Entity Framework 6.1, ASP.NET MVC 5.1.1 for those who wonder.

Gup3rSuR4c
  • 9,145
  • 10
  • 68
  • 126

2 Answers2

4

Try this instead of the custom converters..

Mapper.CreateMap<Company, CompanyDto>()
      .ForMember(d => d.CreatedDateTime,
        expression => expression.ResolveUsing(s=>s.CreatedDateTime.ToString("g")));

// now do the Mapper.Map from Company to CompanyDto.
Raja Nadar
  • 9,409
  • 2
  • 32
  • 41
  • Tried it, now I'm getting: *Object reference not set to an instance of an object.* I know the property has a value because it can't be null in the database. – Gup3rSuR4c Mar 31 '14 at 04:08
  • can you paste the full code and the stack trace of exception? – Raja Nadar Mar 31 '14 at 04:10
  • The database makes no difference. What matters is if the type is nullable in code. – Simon Whitehead Mar 31 '14 at 04:11
  • Also, put a breakpoint and check the value of CompanyObject.CreatedDateTime value. (assuming the null reference there) – Raja Nadar Mar 31 '14 at 04:12
  • The value isn't null, I guarantee that. While debugging the latest exception, I noticed that the inner exception was: *Duplicate type name within an assembly.*; which is somehow coming from the `DbContext` only on the `Company` set. I see the data in the database, and it's not null, so Idk what gives. To be honest, I'm just going to manually map for now and I *might* revisit AutoMapper in the future. I've simply had it with AutoMapper and all the weirdness I keep getting in my application. I'll accept your answer because I presume you are correct in case someone else finds this in the future. – Gup3rSuR4c Mar 31 '14 at 04:41
3

You can also simply use the MapFrom method instead of the ResolveUsing

public class EFObject
{
    public DateTime D { get; set; }
}
public class DTOObject
{
    public string DS { get; set; }
}

internal class Program
{
    private static void Main(string[] args)
    {
        Mapper.CreateMap<EFObject, DTOObject>().
            ForMember(dtoo => dtoo.DS, opt => opt.MapFrom(efo => efo.D.ToString("g")));

        var fromDB = new EFObject() { D = DateTime.Now };
        var toDTO = Mapper.Map<EFObject, DTOObject>(fromDB);
    }
}

I'd recommend using MapFrom instead of ResolveUsing since MapFrom adds some null checking along the resolution path (among other things). Here is a good discussion about the subject

Community
  • 1
  • 1
samy
  • 14,832
  • 2
  • 54
  • 82
  • +1 to use the MapFrom. In my case I am using a Func parameter for MapFrom where I had to explicitly map from one date column to another (in a list) – Trevor Feb 15 '17 at 11:12