Dimitar
Dimitar

Reputation: 1

How to fix the unmapped members?

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.sstatic.net/E5ONd.png

Upvotes: 0

Views: 351

Answers (3)

Edward
Edward

Reputation: 29996

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

Upvotes: 0

Gerald Chifanzwa
Gerald Chifanzwa

Reputation: 1347

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.

Upvotes: 1

Henk Mollema
Henk Mollema

Reputation: 46561

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)

Upvotes: 0

Related Questions