1
votes

I am trying to include Automapper into project using Entity Framework, this is my DTO class:

public class FunctionDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string Comment { get; set; }
    public DateTime? ExaminationDate { get; set; }
    public string Place { get; set; }
}

And domain class with code first:

public class Function
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public string Comment { get; set; }
    public DateTime? ExaminationDate { get; set; }
    public string Place { get; set; }

    public virtual List<Employee> Employees { get; set; }
}

Automapper configuration:

public static class AutoMapperConfiguration
{
    public static void Configure()
    {
        Mapper.Initialize(config => config.AddProfile<FunctionProfile>());
    }
}

public class FunctionProfile : Profile
{
    protected override void Configure()
    {
        CreateMap<Function, FunctionDto>()
        .ForMember(dto => dto.Id, opt => opt.MapFrom(src => src.Id))
        .ForMember(dto => dto.Name, opt => opt.MapFrom(src => src.Name))
        .ForMember(dto => dto.Comment, opt => opt.MapFrom(src => src.Comment))
        .ForMember(dto => dto.StartDate, opt => opt.MapFrom(src => src.StartDate))
        .ForMember(dto => dto.EndDate, opt => opt.MapFrom(src => src.EndDate))
        .ForMember(dto => dto.ExaminationDate, opt => opt.MapFrom(src => src.ExaminationDate))
        .ForMember(dto => dto.Place, opt => opt.MapFrom(src => src.Place));
    }   
}

Then use in WebApi:

var functionDtos = functions
            .AsQueryable()
            .OrderBy(sort)
            .Skip(start)
            .Take(count)
            .ToList()
            .Select(Mapper.Map<FunctionDto>);

Of course I have register in Global:

 AutoMapperConfiguration.Configure();

But I got the exception:

Missing type map configuration or unsupported mapping

What is wrong with the code above?

2
Not an answer (yet) but it would be enough to do CreateMap<Function, FunctionDto>(); because all members have the same names. What happens if you put the initialization statement just before the linq query? (Just for trying)Gert Arnold
@GertArnold: Dto does not have Employees and just be explicit. I tried functions.Select(Mapper.Map<FunctionDto>) and still get the same error. Also Function in here is proxy class because of lazy loadingcuongle
I use AutoMapper 2.1 (Nuget) and it maps from proxies to dto's v.v. I know that proxies could cause problems (there have been questions about it here at SO) but that seems to be OK in the version I use.Gert Arnold

2 Answers

0
votes

Can you please confirm what functions is as the following passes:

MapperConfiguration.cs

namespace StackOverflow.Function
{
    using AutoMapper;

    public class MyProfile : Profile
    {
        protected override void Configure()
        {
            CreateMap<Function, FunctionDto>();
        }
    }
}

MappingTests.cs

[TestFixture]
public class MappingTests
{
    [Test]
    public void AutoMapper_Configuration_IsValid()
    {
        Mapper.Initialize(m => m.AddProfile<MyProfile>());
        Mapper.AssertConfigurationIsValid();
    }

    [Test]
    public void AutoMapper_Mapping_IsValid()
    {
        Mapper.Initialize(m => m.AddProfile<MyProfile>());
        Mapper.AssertConfigurationIsValid();

        var functions = new List<Function>
            {
                new Function
                    {
                        Comment = "Stack Overflow Rocks",
                        EndDate = new DateTime(2012, 01, 01),
                        ExaminationDate = new DateTime(2012, 02, 02),
                        Id = 1,
                        Name = "Number 1",
                        Place = "Here, there and everywhere",
                        StartDate = new DateTime(2012, 03, 03)
                    },
                new Function
                    {
                        Comment = "As do I",
                        EndDate = new DateTime(2013, 01, 01),
                        ExaminationDate = new DateTime(2013, 02, 02),
                        Id = 2,
                        Name = "Number 2",
                        Place = "Nowhere",
                        StartDate = new DateTime(2013, 03, 03)
                    }
            };

        var functionDtos = functions
            .AsQueryable()
            .OrderBy(x => x.Id)
            .Skip(1)
            .Take(1)
            .ToList()
            .Select(Mapper.Map<FunctionDto>);

        Assert.That(functionDtos, Is.Not.Null);
        Assert.That(functionDtos.Count(), Is.EqualTo(1));
        Assert.That(functionDtos.First().Id, Is.EqualTo(2));
    }
}
0
votes

Try this Configure() method,

Note: If the Function, FunctionDto has same name properties you do not need to map. AutoMapper will take care mapping.

protected override void Configure()
{
    CreateMap<Function, FunctionDto>().IgnoreAllNonExisting();
}

--

    public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    {
        var sourceType = typeof(TSource);
        var destinationType = typeof(TDestination);
        var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
        foreach (var property in existingMaps.GetUnmappedPropertyNames())
        {
            expression.ForMember(property, opt => opt.Ignore());
        }
        return expression;
    }