In my ASP.NET Core Web API, I have IdentityDbContext:
public class MyDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, long, IdentityUserClaim<long>, ApplicationUserRole, IdentityUserLogin<long>, IdentityRoleClaim<long>, IdentityUserToken<long>>
{
public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
public DbSet<ApplicationRole> ApplicationRole { get; set; }
public DbSet<ApplicationUserRole> ApplicationUserRole { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<ApplicationUser>(entity =>
{
entity.Property(u => u.Id).ValueGeneratedOnAdd();
entity.HasIndex(u => u.Email).IsUnique();
entity.HasIndex(u => u.UserName).IsUnique();
});
builder.Entity<ApplicationRole>(entity =>
{
entity.Property(r => r.Id).ValueGeneratedOnAdd();
entity.HasIndex(r => r.Name).IsUnique();
});
}
IdentityModel:
public class ApplicationUser : IdentityUser<long>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string MobileNumber { get; set; }
[JsonIgnore]
public bool? IsDeleted { get; set; }
public DateTime? LastLogin { get; set; }
public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationRole : IdentityRole<long>
{
public ICollection<ApplicationUserRole> UserRoles { get; set; }
}
public class ApplicationUserRole : IdentityUserRole<long>
{
public override long UserId { get; set; }
public override long RoleId { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual ApplicationRole Role { get; set; }
}
}
LoginRequestDto:
public class LoginRequestDto
{
[Required]
[JsonProperty(PropertyName = "username")]
public string UserName { get; set; }
[Required(ErrorMessage = "The password is required!")]
public string Password { get; set; }
}
UserDto:
public class UserDto
{
public long Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string MobileNumber { get; set; }
public DateTime LastLogin { get; set; }
}
AuthMapper:
public class AuthMapperProfile : Profile
{
public AuthMapperProfile()
{
CreateMap<ApplicationUser, UserDto>();
}
Services:
public interface IAuthService
{
Task<GenericResponseDto<object>> LoginUser(LoginRequestDto request);
}
public class AuthService : IAuthService
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
private readonly IConfiguration _configuration;
private readonly IMapper _mapper;
private readonly MyDbContext _context;
public AuthService(
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager,
IConfiguration configuration,
IMapper mapper,
MyDbContext context
)
{
_userManager = userManager;
_roleManager = roleManager;
_configuration = configuration;
_mapper = mapper;
_context = context;
}
public async Task<GenericResponseDto<object>> LoginUser(LoginRequestDto request)
{
var user = await _userManager.FindByNameAsync(request.UserName);
var response = new GenericResponseDto<object>();
if (user != null && await _userManager.CheckPasswordAsync(user, request.Password))
{
var roles = await _userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in roles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
response.Result = new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
user = _mapper.Map<UserDto>(user),
expires = token.ValidTo
};
response.StatusCode = 200;
user.LastLogin = DateTime.Now;
try
{
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
response.Error = new ErrorResponseDto() { ErrorCode = 500, Message = ex.Message };
}
return response;
}
response.StatusCode = 400;
response.Error = new ErrorResponseDto { ErrorCode = 400, Message = "Invalid Username or Password!" };
return response;
}
}
I got this error:
AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types: Object -> UserDto System.Object -> DDM.API.Core.DTOs.v1.Authentication.UserDto at lambda_method198(Closure , Object , UserDto , ResolutionContext ) at DDM.API.Core.Services.v1.Concrete.AuthService.LoginUser(LoginRequestDto request) in C:\Users\MyApp\Core\Services\v1\Concrete\AuthService.cs:line 78
This is line 78:
response.Result = new
startup.cs:
// Auto mapper
services.AddAutoMapper(typeof(Startup));
// Dependency Injection
services.AddScoped<IAuthService, AuthService>();
controller:
[Produces("application/json")]
[HttpPost("login")]
public async Task<ActionResult<GenericResponseDto<object>>> Login(LoginRequestDto loginRequest)
{
var response = await _authService.LoginUser(loginRequest);
Response.StatusCode = response.StatusCode ?? StatusCodes.Status200OK;
return new JsonResult(response);
}
What do I do to resolve this?
Thanks
userisApplicationUser?