I have the following value resolver:
public class StudentResolver : IValueResolver<Lesson, LessonResponse, UserResponse>
{
private readonly ApplicationDbContext _dbContext;
public StudentResolver(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public UserResponse Resolve(
Lesson lesson,
LessonResponse response,
UserResponse member,
ResolutionContext context)
{
var user = _dbContext.Users
.Where(x => x.Id == lesson.StudentId)
.FirstOrDefault();
if (user == null)
return null;
var result = Mapper.Map<UserResponse>(user); // this line triggers a "no parameterless constructor", why?
return result;
}
}
This resolver tries to fetch the Student
attribute for this model:
public class LessonResponse
{
public string Id { get; set; }
public UserResponse Student { get; set; }
}
But on the line:
var result = Mapper.Map<UserResponse>(user);
I get:
{System.MissingMethodException: No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at AutoMapper.MappingOperationOptions`2.CreateInstanceT}
The only type in that expression that should be created is UserResponse
which is defined as follows:
public class UserResponse
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Picture { get; set; }
public string X { get; set; }
public bool IsAdmin { get; set; }
public bool IsClient { get; set; }
public bool IsInstructor { get; set; }
}
But it is constructible, so what am I doing wrong?
The mapping profile is the following:
public class MappingProfile : Profile
{
public MappingProfile() {
CreateMap<Lesson, LessonResponse>()
.ForMember(
dest => dest.Student,
opts => opts.ResolveUsing<StudentResolver>());
}
}
And the mapping for the user is:
public class MappingProfile : Profile
{
public MappingProfile() {
CreateMap<ApplicationUser, UserResponse>()
.ForMember(
dest => dest.FullName,
opts => opts.MapFrom(
origin => origin.FirstName + " " + origin.LastName))
.ForMember(
dest => dest.IsAdmin,
opts => opts.ResolveUsing<IsAdminResolver>())
.ForMember(
dest => dest.IsInstructor,
opts => opts.ResolveUsing<IsInstructorResolver>())
.ForMember(
dest => dest.IsClient,
opts => opts.ResolveUsing<IsClientResolver>());
}
}
The boolean resolvers are all similar to:
public class IsAdminResolver : IValueResolver<ApplicationUser, UserResponse, bool>
{
private readonly UserManager<ApplicationUser> _userManager;
public IsAdminResolver(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public bool Resolve(ApplicationUser user, UserResponse response, bool member, ResolutionContext context)
{
return _userManager.IsInRoleAsync(user, "Admin").Result;
}
}
I had the same problem because of my inattention. I generated it with Visual Studio quick tip default constructor for the class inherited from Profile
which was protected
instead of public
. I hope this will help somebody.
sorry for long response time since yesterday was exhausted after work.
I was able to replicate your issue. You have 2 options:
1st Option Resolve your StudentResolver
with your DbContext
:
CreateMap<Lesson, LessonResponse>()
.ForMember(
dest => dest.Student,
opts => opts.ResolveUsing(new StudentResolver(ApplicationDbContext.Create())));
2nd Option, configure your mapper configuration ConstructServicesUsing
. In my case I was using Simple Injector to test things out.
Mapper.Initialize(cfg =>
{
cfg.ConstructServicesUsing(type => container.GetInstance(typeof(StudentResolver)));
cfg.AddProfile<MappingProfile>();
});
For my testing, I was getting an error thrown var lessonResponse = Mapper.Map<LessonResponse>(lesson);
So if your is thrown for Mapper.Map<UserResponse>(user);
you may have to ConstructService for IsAdminResolver
, IsInstructorResolver
and IsClientResolver
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