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
时,您需要告诉它所有 Profile
s 住在哪里。如果AuthMapperProfile
与Startup
存在于一个单独的程序集中,那就有问题了。以上是关于ASP.NET Core - AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET Core搭建多层网站架构6.2-使用AutoMapper映射实体对象
automapper 自动映射 集成asp.net Core2.1