【问题标题】:ASP.NET Core - AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mappingASP.NET Core - AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射
【发布时间】:2022-01-20 12:20:54
【问题描述】:

在我的 ASP.NET Core Web API 中,我有 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();
        });
}

身份模型:

 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>();

}

服务:

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;
    }
}

我收到了这个错误:

AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射。

映射类型: 对象-> UserDto System.Object -> DDM.API.Core.DTOs.v1.Authentication.UserDto 在 lambda_method198(闭包,对象,UserDto,ResolutionContext) 在 DDM.API.Core.Services.v1.Concrete.AuthService.LoginUser(LoginRequestDto request) 在 C:\Users\MyApp\Core\Services\v1\Concrete\AuthService.cs:line 78

这是第 78 行:

response.Result = 新

startup.cs:

  // Auto mapper
  services.AddAutoMapper(typeof(Startup));

  // Dependency Injection
  services.AddScoped<IAuthService, AuthService>();

控制器:

    [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);
    }

我该怎么做才能解决这个问题?

谢谢

【问题讨论】:

  • 您的映射器注册为服务是什么样的?请问可以加代码吗?
  • @MartinStaufcik - 请参阅我的代码中的 AuthMapper: 和 startup.cs。谢谢
  • 你能验证user的类型是ApplicationUser吗?
  • @MattU - 是的。在 MyDbContext 中查看
  • 看起来您有多个项目。你可以试试 services.AddAutoMapper(typeof(Startup), typeof(AuthService));另外,尝试将分配移出对象创建

标签: c# asp.net-core


【解决方案1】:

由于某种原因,您的映射 Profile 没有被考虑在内,错误消息支持这一点,错误消息说 Automapper 使用 Object 到 UserDto 的映射,而不是 ApplicationUser 到 UserDto。

尝试以其他方式配置映射器

var config = new MapperConfiguration(cfg => {
    cfg.AddMaps(myAssembly);
});

IMapper mapper = config.CreateMapper();

services.AddSingleton(mapper);

另一种选择,尝试手动映射

var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<ApplicationUser, UserDto>();
});

【讨论】:

  • 基本上我有三 (3) 个项目: 1. DDM.API.Infrasteucture(它包含数据库迁移和实体。它被 DDM.API.Core 引用)。 2. DDM.API.Core(它包含 DTO 和服务。这是完成映射的地方。它由 DDM.API.Web 引用)。 3. DDM.API.Web(由startup.cs组成)
  • The documentation for injection 声明您使用配置文件定义配置。然后让 AutoMapper 知道通过调用 AddAutoMapper 方法定义的配置文件在哪些程序集中。您需要提供配置文件类型作为参数:services.AddAutoMapper(typeof(AuthMapperProfile));。
  • @mike 正如 Martin 指出的那样,当您 AddAutoMapper 时,您需要告诉它所有 Profiles 住在哪里。如果AuthMapperProfile 与Startup 存在于一个单独的程序集中,那就有问题了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 2021-11-21
  • 2019-03-01
  • 2017-04-16
  • 2015-09-22
  • 1970-01-01
相关资源
最近更新 更多