How to fix the unmapped members?

324 Views Asked by At

I am building a new project for browsing through movies and giving your opinion for them. Now I am on the administration part and I added functionality for adding a movie but when I try to add a movie the automapper throws exception for unmapped members on the service where I am mapping dto to data model. The members are from the base data model for example the id.

EDIT:

I tried to ignore all the members that make this exception, also tried to made a constructor with no arguments but doesn't work.

// Initialization
Mapper.Initialize(conf =>
        {
            conf.CreateMap<Movie, MovieDto>();
            conf.CreateMap<MovieDto, Movie>();
            conf.CreateMap<MovieDto, MovieViewModel>();
        });

// Base Data Model
public class DataModel
{
    [Key]
    public int Id { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime? CreatedOn { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime? ModifiedOn { get; set; }

    public bool IsDeleted { get; set; }

    [DataType(DataType.DateTime)]
    public DateTime? DeletedOn { get; set; }
}

// Movie Data Model
public class Movie: DataModel
{

    public Movie(string title, double rating, string duration, string type, string description, DateTime releaseDate, string producer)
    {
        this.Title = title;
        this.Rating = rating;
        this.Duration = duration;
        this.Type = type;
        this.Description = description;
        this.ReleaseDate = releaseDate;
        this.Producer = producer;
    }

    // successfully mapped members
}

// Movie DTO
public class MovieDto
{
    public string Title { get; set; }

    public double Rating { get; set; }

    public string Duration { get; set; }

    public string Type { get; set; }

    public string Description { get; set; }

    public DateTime ReleaseDate { get; set; }

    public string Producer { get; set; }
}

 // Add functionality 
 public void AddMovie(MovieDto movie)
 {
      //execption here
      var movieDM = this.mapper.Map<Movie>(movie);

      this.repo.Add(movieDM);

      this.saver.SaveChanges();
 }

This is the exception on img: https://i.stack.imgur.com/E5ONd.png

3

There are 3 best solutions below

4
Henk Mollema On

You can specify that AutoMapper should not validate that all properties are being mapped. The MemberList enum can be used for this when creating the mapping configuration. For example:

conf.CreateMap<MovieDto, Movie>(MemberList.None)

The error in the screenshot however indicates that another mapping is problematic, the one from MovieViewModel to MovieDto. I suggest you add a mapping configuration for these types as well:

conf.CreateMap<MovieViewModel, MovieDto>(MemberList.None)
0
Gerald Chifanzwa On

Got it to work by doing the following. Firstly, since DataModel is a base class, I followed automapper's mapping inheritance (see docs). Then since you are using a mapper instance to map this.mapper.Map<Movie>(movie), the configuration needs to be instance rather than static as well, and I use the AutoMapper.Extensions.Microsoft.DependencyInjection nuget package for this, which allows registering Automapper with the IoC container.

My configuration looks like this (inside the ConfigureServices method of the Startup class).

            services.AddAutoMapper(conf =>
        {
            conf.CreateMap<object, DataModel>()
                .ForMember(d => d.Id, opts => opts.Ignore())
                .ForMember(d => d.CreatedOn, opts => opts.MapFrom(_ => DateTime.Now))
                .ForMember(d => d.ModifiedOn, opts => opts.MapFrom(_ => DateTime.Now))
                .ForMember(d => d.DeletedOn, opts => opts.MapFrom(_ => (DateTime?)null))
                .ForMember(d => d.IsDeleted, opts => opts.MapFrom(_ => false))
                .Include<MovieDto, Movie>();
            conf.CreateMap<Movie, MovieDto>();
            conf.CreateMap<MovieDto, Movie>();
        });

Note that I used CreateMap<object, DataModel> for the base class mapping and just used hardcoded values for dates there, feel free to adjust to suit your scenario.

After injecting an instance of IMapper, I was able to call this.mapper.Map<Movie>(movie) successfully.

Hope this sets u off in a good direction.

0
Edward On

You could try Profile Instances.

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<OrderViewModel, Order>()
            .ForMember(dest => dest.OrderItem, opt => opt.MapFrom(src => src.OrderItemViewModel));
        CreateMap<OrderItemViewModel, OrderItem>();
        CreateMap<Order, Order>()
            .ForMember(dest => dest.Id, opt => opt.Ignore());

        CreateMap<Movie, MovieDto>();
        CreateMap<MovieDto, Movie>();
    }
}

Here is the working demo AutoMapperProfile