Automapper is throwing this error at me: Missing map from String to String. Create using Mapper.CreateMap<String, String>.
The map is used in two places. in one place it works fine, in another it fails.
The mapping profile is this:
public class AdminUserProfileProfile: Profile
{
protected override void Configure()
{
Mapper.CreateMap<AdminUser, AdminUserProfile>()
.ForMember(vm => vm.Id, opt => opt.MapFrom(m => m.Id))
.ForMember(vm => vm.Name, opt => opt.MapFrom(m => m.Name))
.ForMember(vm => vm.Email, opt => opt.MapFrom(m => m.Email))
.ForMember(vm => vm.Roles, opt => opt.MapFrom(m => m.Roles.Select(r => r.Name)))
.IgnoreAllNonExisting();
}
}
The only difference in use case is that the mapping which behaves as expected uses Mapper.Map<AdminUserProfile>(entity)
and the one that fails is used via a `Project().To' call.
I would like to use the projection capabilities of Project().To<>
, what do I need to do to get this to work?
Just spent some time in the AutoMapper
source figuring this out. The issue comes from a bug in type handling, but there's not an easy fix in the automapper source.
TL;DR: If you make AdminUserProfile.Roles
be of type IEnumerable<string>
, I think it will work.
.ForMember(vm => vm.Roles, opt => opt.MapFrom(m => m.Roles.Select(r => r.Name)))
I'll bet a dollar AdminUserProfile.Roles
is something like string[]
, ICollection<string>
, or List<string>
.
AutoMapper is trying to assemble a linq query that looks kinda like this:
admins.Select(a => new AdminUserProfile{
Id = a.Id,
Name = a.Name,
Roles = a.Roles.Select(r => r.Name)
})
But that isn't legal, because the types on Roles = a.Roles.Select(r => r.Name)
don't match. In my case, my Roles
property was a ICollection<string>
, but a.Roles.Select
is returning an IEnumerable<string>
, and you can't assign those directly.
I patched the automapper source to fix the Missing map from String to String.
error, and once past that it will try to add a ToList
in there, generating something like:
admins.Select(a => new AdminUserProfile{
Id = a.Id,
Name = a.Name,
Roles = a.Roles.Select(r => r.Name).ToList()
})
This is neat, but if you use it with Linq-to-entities you'll get a runtime LINQ to Entities does not recognize the method ToList
error.
I think the "real" fix would be to make significant changes to automapper and have it generate something like:
admins.Select(a => new {
a.Id,
a.Name,
Roles = a.Roles.Select(r => r.Name)
})
.AsEnumerable() // run the linq-to-entities query
.Select(a => new AdminUserProfile{
Id = a.Id,
Name = a.Name,
Roles = a.Roles.ToList()
})
The code is pretty dense, so I'm unlikely to make this fix.
I'd recommend just change AdminUserProfile.Roles
to IEnumerable<string>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With