kay
kay

Reputation: 195

Automapper Expression Error: Null Reference/Error Mapping Types and ReverseMap

I am trying to use AutoMapper to map between two models in an expression, but receiving an error from AutoMapper: "Error Mapping Types" with an Inner Exception Message of "Object reference not set to an instance of an object."

I set up my configuration and defined the mapping by following the wiki on Github:

Configuration

Expression Translation

Below is a very simplified example that produces the error using version AutoMapper 5.1.1.

Models to Map

Note: I only need to map from Model1 to Model2.

public class Model1
{
    public int Id { get; set; }
}

public class Model2
{
    public int Id { get; set; }
} 

Configuration:

public static class AutoMapperConfig
{
    public static IMapper Mapper;

    static AutoMapperConfig()
    {
        var config = new MapperConfiguration(c => {
          // Produces error
          CreateMap<Model1, Model2>();

          //The below definitions do NOT produce error
          CreateMap<Model1, Model2>().ReverseMap();
          //OR
          CreateMap<Model1, Model2>();
          CreateMap<Model2, Model1>();
          //OR
          CreateMap<Expression<Func<Model1,bool>>, Expression<Func<Model2,bool>>>();

        });

        Mapper = config.CreateMapper();
    }
}

Usage:

Expression<Func<Model1, bool>> model1Expr = x => x.Id == 2;
var model2Expr =  AutoMapperConfig.Mapper.Map<Expression<Func<Model2,bool>>>(model1Expr);

I receive the error at the line that declares the model2Expr variable above.

Error From Elmah :(

[NullReferenceException: Object reference not set to an instance of an object.]
AutoMapper.Mappers.MappingVisitor.PropertyMap(MemberExpression node) +109
AutoMapper.Mappers.MappingVisitor.VisitMember(MemberExpression node) +95
System.Linq.Expressions.MemberExpression.Accept(ExpressionVisitor visitor) +14
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) +22
AutoMapper.Mappers.MappingVisitor.VisitBinary(BinaryExpression node) +73
System.Linq.Expressions.BinaryExpression.Accept(ExpressionVisitor visitor) +14
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) +22
AutoMapper.Mappers.ExpressionMapper.Map(TSource expression, ResolutionContext context) +1534
lambda_method(Closure , Object , Object , ResolutionContext ) +183

[AutoMapperMappingException: Error mapping types.

IMPORTANT: A coworker noted that the error is not encountered when two way mapping is defined (with either ReverseMap or two separate CreateMap statements), or when the mapping is defined explicitly as being between to Expression types. The Expression Translation link above does define two way mapping between the models, but does not explicitly mention requiring it.

Question:

Am I somehow messing up the configuration and/or map definition, or are two way mapping definitions required when mapping between objects in expressions and the wiki is just not explicitly stating it?


UPDATE: I opened an issue on AutoMapper GitHub. As of right now it seems that

Yes the order is backwards when doing expression translation.

Basically this means that if you want to map between expressions, create a mapping definition in the opposite direction of your desired mapping:

CreateMap<Model2, Model1>();
//....
Expression<Func<Model1, bool>> model1Expr = x => x.Id == 2;
var model2Expr =  AutoMapperConfig.Mapper.Map<Expression<Func<Model2,bool>>>(model1Expr);

Upvotes: 4

Views: 6755

Answers (1)

CodingYoshi
CodingYoshi

Reputation: 27039

You need to call the ReverseMap as below:

static AutoMapperConfig()
{
    var config = new MapperConfiguration(c => {
      CreateMap<Model1, Model2>().ReverseMap(); // <======
    });

    Mapper = config.CreateMapper();
}

Upvotes: 1

Related Questions