4

I'm getting the following error in AutoMapper when trying to convert an object with a property that is of type byte[] to an object with a matching property of type string:

System.InvalidOperationException: Missing map from System.Byte to System.Char. Create using CreateMap<Byte, Char>.

I tried using custom type converters, but they didn't seem to work (same error with or without them). I was able to map the specific property, but I'm trying to create something that can be applied to an entire project (most of my entities include a RowVersion that is intended to be used for optimistic locking).

My code look something like this...

public class AutoMapperProfile : AutoMapper.Profile
{
    public AutoMapperProfile()
    {
        CreateMap<byte[], string>().ConvertUsing<ByteArrayToStringTypeConverter>();
        CreateMap<string, byte[]>().ConvertUsing<StringToByteArrayTypeConverter>();
        CreateMap<MyFirstClass, MySecondClass>();
    }
}
public class MyFirstClass
{
    public string Name { get; set; }
    public byte[] RowVersion { get; set; }
}

public class MySecondClass
{
    public string Name { get; set; }
    public string RowVersion { get; set; }
}

public class ByteArrayToStringTypeConverter : ITypeConverter<byte[], string>
{
    public string Convert(byte[] source, string destination, ResolutionContext context)
    {
        return System.Convert.ToBase64String(source);
    }
}

public class StringToByteArrayTypeConverter : ITypeConverter<string, byte[]>
{
    public byte[] Convert(string source, byte[] destination, ResolutionContext context)
    {
        return System.Convert.FromBase64String(source);
    }
}

This is in a .Net 5, ASP.Net Core, Web API project.

Brian
  • 37,399
  • 24
  • 94
  • 109
  • Did you try add your converters into global `ValueTransformers` collection ? – Batuhan Aug 18 '21 at 23:50
  • Is your profile registered with AutoMapper? – Rowan Freeman Aug 19 '21 at 00:03
  • Has your information registration process been completed?For more methods of custom type converters, please refer to:https://docs.automapper.org/en/stable/Custom-type-converters.html – Tupac Aug 19 '21 at 09:02
  • The profile is registered using the ASP.Net Core service extension method `services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());`. I am fairly confident this is working since I can map data between objects, just getting the error when one of those is a byte[] to string conversion. – Brian Aug 19 '21 at 16:08

1 Answers1

5

TypeConverters work fine on my end:

Given these classes:

class DatabaseRecord
{
    public byte[] RowVersion { get; set; }
}

class Dto
{
    public string RowVersion { get; set; }
}

and this mapping configuration

public class Mappings : Profile
{
    public static IMapper Mapper = new MapperConfiguration(c => c.AddProfile(new Mappings())).CreateMapper();

    public Mappings()
    {
        CreateMap<string, byte[]>().ConvertUsing<Base64Converter>();
        CreateMap<byte[], string>().ConvertUsing<Base64Converter>();
        CreateMap<DatabaseRecord, Dto>().ReverseMap();
    }

    private class Base64Converter : ITypeConverter<string, byte[]>, ITypeConverter<byte[], string>
    {
        public byte[] Convert(string source, byte[] destination, ResolutionContext context) 
            => System.Convert.FromBase64String(source);

        public string Convert(byte[] source, string destination, ResolutionContext context) 
            => System.Convert.ToBase64String(source);
    }
}

@Lucian Bargaoanu points out this can be shortened with inline converters:

CreateMap<string, byte[]>().ConvertUsing(s => System.Convert.FromBase64String(s));
CreateMap<byte[], string>().ConvertUsing(bytes => System.Convert.ToBase64String(bytes));
CreateMap<DatabaseRecord, Dto>().ReverseMap();

I can convert string (base64) to byte[] and back without any issues:

var result = Mappings.Mapper.Map<Dto>(new DatabaseRecord
{
    RowVersion = new byte[]{104,101,108,108,111} // "hello"
});
Console.WriteLine(result.RowVersion); // outputs "aGVsbG8="

var record = Mappings.Mapper.Map<DatabaseRecord>(new Dto
{
    RowVersion = "aGVsbG8=" // "hello" in base64
});
// record.RowVersion == 104,101,108,108,111
abdusco
  • 9,700
  • 2
  • 27
  • 44