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 шт):

Автор решения: air

Все оказалось настолько просто, что ужас. Оказывается при регистрации моего класса Mapper он ссылался на такой же класс из библиотеки AutoMapper.

Исправил это, добавив корректное пространство имен

services.AddAutoMapper(typeof(application.AutoMapper.Mapper));
→ Ссылка