AutoMapper Missing type map configuration or unsupported mapping
Пытаюсь смапить DTO в модель, но получаю ошибку о неверной конфигурации или неподдерживаемом маппинге.
Не знаю, может это как-то влияет, но DTO, Models, и класс Mapper находятся в разных сборках
Ссылка на репозиторий: https://github.com/air2921/JobQuest
Не совсем понимаю из-за чего это происходит, на иностранном SO пишут, что это происходит из-за того что я пытаюсь использовать AutoMapper перед тем как зарегистрировать его, но я не понимаю как это возможно, ибо я регистрирую AutoMapper в DI контейнере ASP.NET Core.
Вот так пытаюсь маппить:
public async Task<Response> AddSingle(CompanyDTO dto, int userId)
{
try
{
var model = mapper.Map<CompanyModel>(dto);
model.UserId = userId;
await repository.AddAsync(model);
return Response(201);
}
catch (EntityException ex)
{
return Response(500, ex.Message);
}
}
Вот модель
[Table("Companies")]
public class CompanyModel : Contact
{
[Key]
[JsonPropertyName("company_id")]
public int CompanyId { get; set; }
[Column]
[JsonPropertyName("company_name")]
public string CompanyName { get; set; } = null!;
[Column]
[JsonPropertyName("location")]
public string Location { get; set; } = null!;
[Column]
[JsonPropertyName("register_date")]
public DateTime RegisterDate { get; set; }
[ForeignKey("UserId")]
[JsonPropertyName("user_id")]
public int UserId { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[JsonPropertyName("user")]
public UserModel User { get; set; } = null!;
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[JsonPropertyName("vacancies")]
public ICollection<VacancyModel> Vacancies { get; set; } = [];
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[JsonPropertyName("reviews")]
public ICollection<ReviewModel> Reviews { get; set; } = [];
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[JsonPropertyName("employer_chats")]
public ICollection<ChatModel> EmployerChats { get; set; } = [];
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
[JsonPropertyName("sent_messages_as_employer")]
public ICollection<MessageModel> SentMessagesAsEmployer { get; set; } = [];
}
Вот DTO:
public class CompanyDTO
{
public string CompanyName { get; set; } = null!;
public string Location { get; set; } = null!;
public DateTime RegisterDate { get; set; }
public string? PhoneNumber { get; set; }
public string? Email { get; set; }
public string? Telegram { get; set; }
public string? Github { get; set; }
public string? LinkedIn { get; set; }
public string? WebSite { get; set; }
}
Вот так вот в слое приложения регистрирую AutoMapper
Пробовал так:
services.AddAutoMapper(typeof(Mapper).Assembly);
И так тоже:
services.AddAutoMapper(typeof(Mapper));
Вот так регистрирую слои, в том числе и слой приложения:
public void ConfigureServices(IServiceCollection services)
{
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var config = new ConfigurationBuilder()
.AddUserSecrets<Startup>()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.AddEnvironmentVariables()
.Build();
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.Enrich.WithProperty("Environment", env)
.ReadFrom.Configuration(config)
.WriteTo.Console()
.WriteTo.Elasticsearch(ConfigurationElasticSink(config))
.CreateLogger();
services.AddLogging(log =>
{
log.ClearProviders();
log.AddSerilog(Log.Logger);
});
services.AddBackground();
services.AddDataHub(config, Log.Logger);
services.AddApplication(config, Log.Logger);
services.AddInfrastructure(config, Log.Logger);
services.AddStartupServices(config, environment);
}
Вот профиль маппера:
public class Mapper : Profile
{
public Mapper()
{
CreateMap<ChatDTO, ChatModel>()
.ForMember(x => x.CandidateUser, options => options.Ignore())
.ForMember(x => x.EmployerUser, options => options.Ignore())
.ForMember(x => x.Messages, options => options.Ignore());
CreateMap<MessageDTO, MessageModel>()
.ForMember(x => x.Candidate, options => options.Ignore())
.ForMember(x => x.Employer, options => options.Ignore())
.ForMember(x => x.Chat, options => options.Ignore());
CreateMap<LanguageDTO, LanguageModel>()
.ForMember(x => x.User, options => options.Ignore());
CreateMap<ResponseDTO, ResponseModel>()
.ForMember(x => x.Resume, options => options.Ignore())
.ForMember(x => x.Vacancy, options => options.Ignore());
CreateMap<CompanyDTO, CompanyModel>()
.ForMember(x => x.User, options => options.Ignore())
.ForMember(x => x.EmployerChats, options => options.Ignore())
.ForMember(x => x.Reviews, options => options.Ignore())
.ForMember(x => x.SentMessagesAsEmployer, options => options.Ignore())
.ForMember(x => x.EmployerChats, options => options.Ignore());
CreateMap<ResumeDTO, ResponseModel>()
.ForMember(x => x.Resume, options => options.Ignore())
.ForMember(x => x.Vacancy, options => options.Ignore());
CreateMap<ExperienceDTO, ExperienceModel>()
.ForMember(x => x.Resume, options => options.Ignore());
CreateMap<EducationDTO, EducationModel>()
.ForMember(x => x.Resume, options => options.Ignore());
CreateMap<VacancyDTO, VacancyModel>()
.ForMember(x => x.Company, options => options.Ignore())
.ForMember(x => x.Favorites, options => options.Ignore())
.ForMember(x => x.Responses, options => options.Ignore());
CreateMap<ReviewDTO, ReviewModel>()
.ForMember(x => x.Company, options => options.Ignore())
.ForMember(x => x.User, options => options.Ignore());
}
}
2024-09-02 19:53:11 [16:53:11 ERR] AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
2024-09-02 19:53:11
2024-09-02 19:53:11 Mapping types:
2024-09-02 19:53:11 CompanyDTO -> CompanyModel
2024-09-02 19:53:11 common.DTO.ModelDTO.CompanyDTO -> domain.Models.CompanyModel
2024-09-02 19:53:11 at lambda_method103(Closure, Object, CompanyModel, ResolutionContext)
2024-09-02 19:53:11 at application.Workflows.Core.CompanyWk.AddSingle(CompanyDTO dto, Int32 userId) in /src/src/application/Workflows/Core/CompanyWk.cs:line 83
2024-09-02 19:53:11 at api.Controllers.CompanyController.AddCompany(CompanyDTO dto, IUserInfo userInfo) in /src/src/api/Controllers/CompanyController.cs:line 18
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
2024-09-02 19:53:11 --- End of stack trace from previous location ---
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
2024-09-02 19:53:11 at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|7_0(Endpoint endpoint, Task requestTask, ILogger logger)
2024-09-02 19:53:11 at api.Middlewares.ExceptionCatcherMiddleware.Invoke(HttpContext context) in /src/src/api/Middlewares/ExceptionCatcherMiddleware.cs:line 12
2024-09-02 19:53:11 [16:53:11 INF] Request finished HTTP/2 POST https://localhost:8081/api/companies/add - 500 null application/json; charset=utf-8 565.5131ms
Ответы (1 шт):
Все оказалось настолько просто, что ужас. Оказывается при регистрации моего класса Mapper он ссылался на такой же класс из библиотеки AutoMapper.
Исправил это, добавив корректное пространство имен
services.AddAutoMapper(typeof(application.AutoMapper.Mapper));