R4nc1d
R4nc1d

Reputation: 3113

Automapper with complex configuration

I have a json object

{
  "userId": 12,
  "email": "[email protected]",
  "firstName": "John",
  "lastName": "Smith",
  "customerName": "Microsoft"
  "contents": [
    {
      "productId": 34,
      "productName": "Product 1",
      "productCost": "35.50",
      "quantity": 3
    },
    {
      "productId": 35,
      "productName": "Product 2",
      "productCost": "40.99",
      "quantity": 1
    }
  ]
}

that I post to my WebApi

public IHttpActionResult Post(ShoppingCartDto shoppingCart)
        {    
            var result = _service.AddToCart(shoppingCart);
            return Ok(result);
        }

then I use automapper to map the ShoppingCartDto to all correct domain classes.

So here is the problem, how can use automapper to first to go and lookup an customerId before i actually to the mapping. enter image description here

I have to lookup the customerId from the Customer table so that when i map to the Tokens table i have the customerId

The mapping i have so far

Mapper.CreateMap<ShoppingCartDto, User>()
    .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.UserId))
    .AfterMap((src, dest) =>
    {
        var token = (Mapper.Map<Token>(dest));

        token.CustomerId = "Can I do database lookup here" 

        dest.Tokens.Add(token);

        foreach (var content in Mapper.Map<Cart[]>(src.Contents))
        {
            token.Contents.Add(content);
        }
    });

Or should I use some sort of Custom Resolver.

My mappings are sitting in an AutoMapperConfig file inside the App_Start folder. So I am not a 100% sure how to go about it. I know I can do the mapping manually but i want to keep all the mappings for Automapper

Upvotes: 0

Views: 376

Answers (1)

Yacoub Massad
Yacoub Massad

Reputation: 27861

Since your mapping process requires access to some service (data access in your case), it is better to encapsulate the mapping process in some service like this:

public interface IMapper<TSource, TDestination>
{
    TDestination Map(TSource source);
}

public class ShoppingCartDtoToUserMapper : IMapper<ShoppingCartDto, User>
{
    private IDataAccessor m_DataAccessor; //This can be a repository for example, I am just using IDataAccessor as an example

    public ShoppingCartDtoToUserMapper(IDataAccessor data_accessor)
    {
        m_DataAccessor = data_accessor;
    }

    public User Map(ShoppingCartDto source)
    {
        //Use AutoMapper here as you did and also use m_DataAccessor for any data access operations
    }
}

You should use dependency injection to properly construct the ShoppingCartDtoToUserMapper dependency and inject it (as IMapper<ShoppingCartDto, User>) into the class the requires mapping functionality from ShoppingCartDto to User.

Upvotes: 2

Related Questions