Search code examples
c#.netautomapperdtoconvention-over-configur

How do I map a model with nested properties to a flat Dto?


I'm trying to create a mapping from our entity models to a Dto but I'm failing everytime in trying to create the mapping.

I have two domain classes. This is a simplification of our model (Device for instance has a lot more properties that represent a bunch of different things):

class Device
{
    public int Name {get; set;}
}

class DeviceAccessToken
{
    public Device Device {get; set;}
    public string Key {get; set;}
    public string Secret {get; set;}
}

I then want to map DeviceAccessToken instances to this DeviceDto (also simplified, it has most of the fields present in the original Device model):

class DeviceDto
{
    public int Name {get; set;}
    public string Key {get; set;}
    public string Secret {get; set;}
}

Is there a way to create this mapping without explicitly specifying all fields of the Device domain model in the mapping?

This is effectively what I want, represented by an AutoMapper profile:

class DeviceMappingProfile : Profile
{
    protected override void Configure()
    {
        this.CreateMap<DeviceAccessToken, DeviceDto>();

        this.CreateMap<Device, DeviceDto>()
            .ForMember(dest => dest.Key, opt => opt.Ignore())
            .ForMember(dest => dest.Secret, opt => opt.Ignore());
    }
}

The .ForAllMembers call was a failed attempt to make this work, it must not function like I envisioned it.

I understand I could do this by specifying every property of the Device in the DeviceAccessToken->DeviceDto mapping, but it would be a nightmare and very redundant since the names are the same.


Solution

  • "Is there a way to create this mapping without explicitly specifying all fields of the Device domain model in the mapping?"

    Yes, you can use the naming conventions in your Dto object and this would prevent you having to enter them in the create map.

    As an example:

    Your values Key and Secret exist in DeviceAccessToken and DeviceDto they will not need to be mapped. As Device is a nested object your dto can use the convention of DeviceName.

    Example:

    using System;
    using AutoMapper;
    
    class Device
    {
        public string Name {get; set;}
    }
    
    class DeviceAccessToken
    {
        public Device Device {get; set;}
        public string Key {get; set;}
        public string Secret {get; set;}
    }
    
    class DeviceDto
    {
        public string DeviceName {get; set;}
        public string Key {get; set;}
        public string Secret {get; set;}
    }
    
    public class Program
    {
        public void Main()
        {
    
            // Configure AutoMapper
            Mapper.CreateMap<DeviceAccessToken, DeviceDto>();       
    
            var dat = new DeviceAccessToken { Device = new Device { Name = "Dev Name" }, Key = "Key", Secret = "Secret" };
    
            var dto = Mapper.Map<DeviceDto>(dat);
    
            Console.WriteLine(dto.DeviceName);
            Console.WriteLine(dto.Key);
            Console.WriteLine(dto.Secret);
        }
    }
    

    Working fiddle