cl0ud
cl0ud

Reputation: 1614

AutoMapper - Map Derived Class To Dto

Im trying to map a Class which inherits from a base class to a dto.

public class LaunchConfiguration : Document
{
     public string Brand { get; set; }
     public string SettingName{ get; set; }
}

public class LaunchConfigurationDto
{
     public string Brand { get; set; }
     public string SettingName{ get; set; }
}

The point of the dto is to hide the fields of the base document when it gets returned to the user. This is my Map configuration

public class DtoProfile : Profile
{
    public DtoProfile()
    {
        CreateMap<LaunchConfiguration,LaunchConfigurationDto>();
    }
};

The problem im having is that auto mapper complains about the base class properties which are not mapped . "Unmapped members were found." The properties are the ones on the base class. I have tried specifying this to be ignored in the profile to no avail . Can anyone specify the correct way to do this ?

My ConfigureServices Method incase anyone is wondering :

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new Info { Title = Configuration["ApiInformation:Name"], Version = Configuration["ApiInformation:Version"] });
            c.DescribeAllEnumsAsStrings();
        });

        services.AddAutoMapper(mc =>
        {
            mc.AddProfile(new DtoProfile());
        });
         services.AddMvc().AddJsonOptions(options =>
        {
            options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());
            options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
        });
    }

My Base Class :

 public class Document : IDocument, IDocument<Guid>
{

public Document()
{
  this.Id = Guid.NewGuid();
  this.AddedAtUtc = DateTime.UtcNow;
}

/// <summary>The Id of the document</summary>
[BsonId]
public Guid Id { get; set; }

/// <summary>The datetime in UTC at which the document was added.</summary>
public DateTime AddedAtUtc { get; set; }

/// <summary>The version of the schema of the document</summary>
public int Version { get; set; }
 }

My implementation where _mapper is my Injected mapper and _repo My Injected Repo. Exception Occurs on Map Method call

 Task ILaunchConfigurationService<LaunchConfigurationDto >.InsertLaunchConfiguration(LaunchConfigurationDto model)
    {
         var mapped =  _mapper.Map<LaunchConfiguration >(model);
        return _repo.AddOneAsync(mapped);
    }

Upvotes: 2

Views: 1138

Answers (1)

GrayCat
GrayCat

Reputation: 1795

Your problem should be solved by simply adding ReverseMap() to CreateMap call:

public class DtoProfile : Profile
{
    public DtoProfile()
    {
        CreateMap<LaunchConfiguration, LaunchConfigurationDto>().ReverseMap();
    }
};

Automapper creates one way map by default. ReverseMap is just a sugar for creating reverse map in case there are no peculiar mappings in one way. You could also do it like this:

public class DtoProfile : Profile
{
    public DtoProfile()
    {
        CreateMap<LaunchConfiguration, LaunchConfigurationDto>();
        CreateMap<LaunchConfigurationDto, LaunchConfiguration>();
    }
};

You can read more about this in documentation

However I cannot guarantee you that you will not experience exceptions from database with your current implementation on commiting changes.

Upvotes: 2

Related Questions