ASP.NET Core - AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射

Posted

技术标签:

【中文标题】ASP.NET Core - AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射【英文标题】:ASP.NET Core - AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping 【发布时间】: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));另外,尝试将分配移出对象创建 【参考方案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 住在哪里。如果AuthMapperProfileStartup 存在于一个单独的程序集中,那就有问题了。

以上是关于ASP.NET Core - AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core搭建多层网站架构6.2-使用AutoMapper映射实体对象

automapper 自动映射 集成asp.net Core2.1

3AutoMapper In Asp.net Core

3AutoMapper In Asp.net Core

2021-06-28 .NET高级班 73-ASP.NET Core AutoMapper的使用

ASP.NET Core 中的对象映射之 AutoMapper