AliRıza Adıyahşi
AliRıza Adıyahşi

Reputation: 15866

Automapper missing type map configuration or unsupported mapping - Error

Entity Model

public partial class Categoies
{
    public Categoies()
    {
        this.Posts = new HashSet<Posts>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Nullable<int> PositionId { get; set; }

    public virtual CategoryPositions CategoryPositions { get; set; }
    public virtual ICollection<Posts> Posts { get; set; }
}

View Model

public class CategoriesViewModel
{
    public int Id { get; set; }

    [Required(ErrorMessage = "{0} alanı boş bırakılmamalıdır!")]
    [Display(Name = "Kategori Adı")]
    public string Name { get; set; }

    [Display(Name = "Kategori Açıklama")]
    public string Description { get; set; }

    [Display(Name = "Kategori Pozisyon")]
    [Required(ErrorMessage="{0} alanı boş bırakılmamalıdır!")]
    public int PositionId { get; set; }
}

CreateMap

Mapper.CreateMap<CategoriesViewModel, Categoies>()
            .ForMember(c => c.CategoryPositions, option => option.Ignore())
            .ForMember(c => c.Posts, option => option.Ignore());

Map

[HttpPost]
public ActionResult _EditCategory(CategoriesViewModel viewModel)
{
    using (NewsCMSEntities entity = new NewsCMSEntities())
    {
        if (ModelState.IsValid)
        {
            try
            {
                category = entity.Categoies.Find(viewModel.Id);
                AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel, category);
                //category = AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel);
                //AutoMapper.Mapper.Map(viewModel, category);
                entity.SaveChanges();

                // Veritabanı işlemleri başarılı ise yönlendirilecek sayfayı 
                // belirleyip ajax-post-success fonksiyonuna gönder.
                return Json(new { url = Url.Action("Index") });
            }
            catch (Exception ex)
            {

            }
        }

        // Veritabanı işlemleri başarısız ise modeli tekrar gönder.
        ViewBag.Positions = new SelectList(entity.CategoryPositions.ToList(), "Id", "Name");
        return PartialView(viewModel);
    }
}

Error

Missing type map configuration or unsupported mapping. Mapping types: CategoriesViewModel -> Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D NewsCMS.Areas.Admin.Models.CategoriesViewModel -> System.Data.Entity.DynamicProxies.Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D

Destination path: Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D

Source value: NewsCMS.Areas.Admin.Models.CategoriesViewModel

What am I missing? I try to find, but I cant see problem.

UPDATE

I have specified in application_start in Global.asax

protected void Application_Start()
{
    InitializeAutoMapper.Initialize();
}

InitializeClass

public static class InitializeAutoMapper
{
    public static void Initialize()
    {
        CreateModelsToViewModels();
        CreateViewModelsToModels();
    }

    private static void CreateModelsToViewModels()
    {
        Mapper.CreateMap<Categoies, CategoriesViewModel>();
    }

    private static void CreateViewModelsToModels()
    {
        Mapper.CreateMap<CategoriesViewModel, Categoies>()
            .ForMember(c => c.CategoryPositions, option => option.Ignore())
            .ForMember(c => c.Posts, option => option.Ignore());
    }
}

Upvotes: 142

Views: 404426

Answers (17)

Kainat Tarar
Kainat Tarar

Reputation: 1

In my case the data type of some of the properties of Dto was different than model class. For example, in my InsertUserDto class, the data type of email was "string" while in User class it was "EmailAddressAttribute" and data type of DateOfBirth was "DateTime" in InsertUserDto class and the data type of DateOfBirth was "DateOnly" in User class. Try matching all the data types of each class.

Program.cs:

IMapper mapper = MappingConfig.RegisterMaps().CreateMapper();
builder.Services.AddSingleton(mapper);
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());

Automapper.cs:

public class MappingConfig
{
    public static MapperConfiguration RegisterMaps()
    {
        var mappingConfig = new MapperConfiguration(config =>
        {
            config.CreateMap<InsertUserDto, Users>()
            .ForMember(dest => dest.user_id, option => option.Ignore())
            .ForMember(dest => dest.user_guid, option => option.Ignore())
            .ForMember(dest => dest.created_date, option => option.Ignore())
            .ForMember(dest => dest.updated_date, option => option.Ignore())
            .ForMember(dest => dest.status, option => option.Ignore())
            .ForMember(dest => dest.address_id, option => option.Ignore());
            config.CreateMap<Users, InsertUserDto>();
        });
        return mappingConfig;
    }
}

Upvotes: 0

AliRıza Adıyahşi
AliRıza Adıyahşi

Reputation: 15866

I found the solution, Thanks all for reply.

category = (Categoies)AutoMapper.Mapper.Map(viewModel, category, typeof(CategoriesViewModel), typeof(Categories));

But, I have already dont know the reason. I cant understand fully.

Upvotes: 7

Oscar Agreda
Oscar Agreda

Reputation: 423

From your API controller, it is possible to have an object that resembles a Data Transfer Object (DTO), but is not the actual DTO. In scenarios where different requests for Create, Update, and Delete operations are present, it may be necessary to convert the request without using an Automapping Profile in C#.

    public class CustomerProfile : Profile
{
    public CustomerProfile()
    {
        CreateMap<Customer, CustomerDto>();
    }
}

If that is the case, utilizing a single Data Transfer Object (DTO) for all operations may not be sufficient as the request passed to the controller may be specific to a particular operation. In such instances, it is necessary to include additional request objects.

public class CustomerProfile : Profile
{
    public CustomerProfile()
    {
        CreateMap<Customer, CustomerDto>();
        CreateMap<CustomerDto, Customer>();
        CreateMap<CreateCustomerRequest, Customer>();
        CreateMap<UpdateCustomerRequest, Customer>();
        CreateMap<DeleteCustomerRequest, Customer>();
    }
}

Upvotes: 0

hgiahuyy
hgiahuyy

Reputation: 308

I have solved it hope it helps you :33

For the same type you have to use:

[AutoMap(typeof(UserInfoView))]

[AutoMap(typeof(UserInfoView))]

Upvotes: 0

Mr.B
Mr.B

Reputation: 3787

For .net core with dependency injection I made it work in that way:

builder.Services.AddAutoMapper(config =>
{
    config.CreateMap<CaseModel, Case>();
    config.CreateMap<Case, CaseModel>();
}, AppDomain.CurrentDomain.GetAssemblies());

In that case each instance of mapper with have this mapping configuration.

Mapper user class:

public CaseController(ICaseHttpClient caseHttpClient, IMapper mapper)
{
    _caseHttpClient = caseHttpClient;
    _mapper = mapper;
}

  [HttpGet("{id}")]
        public async Task<ActionResult<CaseModel>> GetById(string id)
        {
            var caseResult = await _caseHttpClient.GetCase(id);
            var caseModelMapped = _mapper.Map<CaseModel>(caseResult);
            return Ok(caseModelMapped);
        }

I hope it helps.

Upvotes: -2

Anton Semenov
Anton Semenov

Reputation: 461

We got the same error after updating from AutoMapper v.3 to v.5.

And eventually we have found that destination class has Property with the type IDictionary<string, object> and at the same type Profile mapping was valid.

There were next possible solutions:

  1. To update to higher version. In the v.6 the bug dissapeared.
  2. Or to ignore that prop in the mapping.
  3. Or to use method Mapper.Map<IFooDto>(foo) instead of Mapper.Map(foo, fooDto).

Our profile was like that using interface as destination:

public class FooProfile : Profile
{
    public FooProfile()
    {
        CreateMap<Foo, IFooDto>()
            .ConstructUsing(foo => new FooDto());
    }
}

Also I should mention that during update from v.3 to higher versions we have met many bugs and differences comparing with old versions and what helped us:

  • Every time to check that maybe next version will fix the bug;
  • Double check existing Mapping configuration. It can have old hidden bugs like mapping to property without a setter or existing duplicated mapping and so on. And it can be that old versions allows this, new does not.

Upvotes: 2

user3542654
user3542654

Reputation: 343

I was trying to map an IEnumerable to an object. This is way I got this error. Maybe it helps.

Upvotes: 25

live-love
live-love

Reputation: 52366

In my case, I had created the map, but was missing the ReverseMap function. Adding it got rid of the error.

      private static void RegisterServices(ContainerBuilder bldr)
      {
         var config = new MapperConfiguration(cfg =>
         {
            cfg.AddProfile(new CampMappingProfile());
         });
         ...
       }


      public CampMappingProfile()
      {
         CreateMap<Talk, TalkModel>().ReverseMap();
         ...
      }

Upvotes: 6

omer
omer

Reputation: 105

I had same issue in .Net Core. Because my base dto class(i give it as a type in startup for automapper assembly) was in different project. Automapper tried to search for profiles in base class project. But my dto's were in different project. I moved my base class. And problem solved. This may help for some persons.

Upvotes: 8

Waldron
Waldron

Reputation: 124

I created a new AutomapperProfile class. It extends Profile. We have over 100 projects in our solution. Many projects have an AutomapperProfile class, but this one was new to this existing project. However, I did find what I had to do to fix this issue for us. There is a Binding project. Within the Initialization there is this code:

var mappingConfig = new List<Action<IConfiguration>>();

// Initialize the Automapper Configuration for all Known Assemblies
mappingConfig.AddRange( new List<Action<IConfiguration>>
{
   ConfigureProfilesInAssemblyOfType<Application.Administration.AutomapperProfile>,
   //...

I had to add ConfigureProfilesInAssemblyOfType<MyNewNamespace.AutomapperProfile>

Note that ConfigureProfilesInAssemblyOfType looks like this:

    private static void ConfigureProfilesInAssemblyOfType<T>( IConfiguration configuration )
    {
        var log = LogProvider.Get( typeof (AutomapperConfiguration) );

        // The Automapper Profile Type
        var automapperProfileType = typeof (Profile);

        // The Assembly containing the type
        var assembly = typeof (T).Assembly;
        log.Debug( "Scanning " + assembly.FullName );

        // Configure any Profile classes found in the assembly containing the type.
        assembly.GetTypes()
            .Where( automapperProfileType.IsAssignableFrom ).ToList()
            .ForEach( x =>
            {
                log.Debug( "Adding Profile '" + x.FullName + "'" );
                configuration.AddProfile( Activator.CreateInstance( x ) as Profile );
            } );
    }

Best regards, -Jeff

Upvotes: -2

Martin4ndersen
Martin4ndersen

Reputation: 2876

Where have you specified the mapping code (CreateMap)? Reference: Where do I configure AutoMapper?

If you're using the static Mapper method, configuration should only happen once per AppDomain. That means the best place to put the configuration code is in application startup, such as the Global.asax file for ASP.NET applications.

If the configuration isn't registered before calling the Map method, you will receive Missing type map configuration or unsupported mapping.

Upvotes: 87

Anand
Anand

Reputation: 21

Upgrade Automapper to version 6.2.2. It helped me

Upvotes: 0

Pierry
Pierry

Reputation: 989

In your class AutoMapper profile, you need to create a map for your entity and viewmodel.

ViewModel To Domain Model Mappings:

This is usually in AutoMapper/DomainToViewModelMappingProfile

In Configure(), add a line like

Mapper.CreateMap<YourEntityViewModel, YourEntity>();

Domain Model To ViewModel Mappings:

In ViewModelToDomainMappingProfile, add:

Mapper.CreateMap<YourEntity, YourEntityViewModel>();

Gist example

Upvotes: 51

kkost
kkost

Reputation: 3730

Check your Global.asax.cs file and be sure that this line be there

 AutoMapperConfig.Configure();

Upvotes: 6

Mitchell Schwitzer
Mitchell Schwitzer

Reputation: 98

I know this is a rather old question as of now, but I had found the proper solution was that I was not declaring the assembly attribute.

My code is:

using AutoMapper;
...

namespace [...].Controllers
{
    public class HousingTenureTypesController : LookupController<HousingTenureType, LookupTypeModel>
    {
        Mapper.CreateMap<HousingTenureType, LookupTypeModel>().ReverseMap();
    }
    ...
}

This was fixed by adding the following line before my namespace declaration:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(HousingTenureTypesController), "AutoMapperStart")]

The full code is:

using AutoMapper;
...

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(HousingTenureTypesController), "AutoMapperStart")]

namespace [...].Controllers
{
    public class HousingTenureTypesController : LookupController<HousingTenureType, LookupTypeModel>
    {
        Mapper.CreateMap<HousingTenureType, LookupTypeModel>().ReverseMap();
    }
    ...
}

Upvotes: 4

Sanchitos
Sanchitos

Reputation: 8591

I did this to remove the error:

Mapper.CreateMap<FacebookUser, ProspectModel>();
prospect = Mapper.Map(prospectFromDb, prospect);

Upvotes: 9

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

Notice the Categoies_7314E98C41152985A4218174DDDF658046BC82AB0ED9E1F0440514D79052F84D class in the exception? That's an Entity Framework proxy. I would recommend you disposing of your EF context to ensure that all your objects are eagerly loaded from the database and no such proxies exist:

[HttpPost]
public ActionResult _EditCategory(CategoriesViewModel viewModel)
{
    Categoies category = null;
    using (var ctx = new MyentityFrameworkContext())
    {
        category = ctx.Categoies.Find(viewModel.Id);
    }
    AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel, category);
    //category = AutoMapper.Mapper.Map<CategoriesViewModel, Categoies>(viewModel, category);
    entity.SaveChanges();
}

If the entity retrieval is performed inside a data access layer (which of course is the correct way) make sure you dispose your EF context before returning instances from your DAL.

Upvotes: 26

Related Questions