I've already seen this question, this and this.
And I've got this exception when I move from Automapper 3.3.1.0
to Automapper 6.0.1.0
. This code throws no exception in Automapper 3.3.1.0
.
I have 2 class :
Class 1 : (Domain)
public class Movie:IEntityBase
{
public Movie()
{
Stocks = new List<Stock>();
}
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public int GenreId { get; set; }
public virtual Genre Genre { get; set; }
public string Director { get; set; }
public string Writer { get; set; }
public string Producer { get; set; }
public DateTime ReleaseDate { get; set; }
public byte Rating { get; set; }
public string TrailerURI { get; set; }
public virtual ICollection<Stock> Stocks { get; set; }
}
Class 2 :
public class MovieViewModel : IValidatableObject
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public string Genre { get; set; }
public int GenreId { get; set; }
public string Director { get; set; }
public string Writer { get; set; }
public string Producer { get; set; }
public DateTime ReleaseDate { get; set; }
public byte Rating { get; set; }
public string TrailerURI { get; set; }
public bool IsAvailable { get; set; }
public int NumberOfStocks { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var validator = new MovieViewModelValidator();
var result = validator.Validate(this);
return result.Errors.Select(item => new ValidationResult(item.ErrorMessage, new[] { item.PropertyName }));
}
}
I've tried to map in constructor of a class cause Automapper 6.0.1.0
does not have method Configure()
to override:
public class DomainToViewModelMappingProfile : Profile
{
public override string ProfileName
{
get { return "DomainToViewModelMappings"; }
}
public DomainToViewModelMappingProfile()
{
Mapper.Initialize(cfg => {
cfg.CreateMap<Genre, GenreViewModel>()
.ForMember(vm => vm.NumberOfMovies, map => map.MapFrom(g => g.Movies.Count()));
cfg.CreateMap<Movie, MovieViewModel>()
.ForMember(vm => vm.Genre, map => map.MapFrom(m => m.Genre.Name))
.ForMember(vm => vm.GenreId, map => map.MapFrom(m => m.Genre.ID))
.ForMember(vm => vm.IsAvailable, map => map.MapFrom(m => m.Stocks.Any(s => s.IsAvailable)))
.ForMember(vm => vm.NumberOfStocks, map => map.MapFrom(m => m.Stocks.Count))
.ForMember(vm => vm.Image, map => map.MapFrom(m => string.IsNullOrEmpty(m.Image) == true ? "unknown.jpg" : m.Image));
});
Mapper.AssertConfigurationIsValid();
}
}
And I've got the following exception:
Missing type map configuration or unsupported mapping.
Mapping types: Movie -> MovieViewModel HomeCinema.Entities.Movie -> HomeCinema.Web.Models.MovieViewModel
I've tried to figure out what property is a reason of this exception through Ignore()
method, however, I still get the above exception.
cfg.CreateMap<Genre, GenreViewModel>()
.ForMember(vm => vm.NumberOfMovies, map => map.MapFrom(g => g.Movies.Count()));
cfg.CreateMap<Movie, MovieViewModel>()
.ForMember(vm => vm.Genre, map => map.Ignore())
.ForMember(vm => vm.GenreId, map => map.Ignore())
.ForMember(vm => vm.IsAvailable, map => map.Ignore())
.ForMember(vm => vm.NumberOfStocks, map => map.Ignore())
.ForMember(vm => vm.Image, map => map.Ignore());
Forgot to say that I am calling the following method in Global.asax.cs
:
AutoMapperConfiguration.Configure();
Could you tell me what I am doing wrong? Any help would be greatly appreciated.
The most interesting point that this code is valid in AutoMapper 3.3.1.0
.
Update:
It works!:) Thanks to all you, guys, and special thanks to @AndriiLitvinov. The work code:
public class DomainToViewModelMappingProfile : Profile
{
public override string ProfileName
{
get { return "DomainToViewModelMappings"; }
}
public DomainToViewModelMappingProfile()
{
CreateMap<Genre, GenreViewModel>()
.ForMember(vm => vm.NumberOfMovies, map => map.MapFrom(g => g.Movies.Count()));
CreateMap<Movie, MovieViewModel>()
.ForMember(vm => vm.Genre, map => map.MapFrom(m => m.Genre.Name))
.ForMember(vm => vm.GenreId, map => map.MapFrom(m => m.Genre.ID))
.ForMember(vm => vm.IsAvailable, map => map.MapFrom(m => m.Stocks.Any(s => s.IsAvailable)))
.ForMember(vm => vm.NumberOfStocks, map => map.MapFrom(m => m.Stocks.Count))
.ForMember(vm => vm.Image, map => map.MapFrom(m => string.IsNullOrEmpty(m.Image) == true ? "unknown.jpg" : m.Image));
}
}
and call Initialize()
just one time:
//Global.asax.cs
protected void Application_Start()
{
var config = GlobalConfiguration.Configuration;
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(config);
Bootstrapper.Run();
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configuration.EnsureInitialized();
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
public class AutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(x =>
{
x.AddProfile<DomainToViewModelMappingProfile>();
});
}
}
public class Bootstrapper
{
public static void `Run()
{
//Configure Autofac
AutofacWebapiConfig.Initialize(GlobalConfiguration.Configuration);
//Configure Automapper
AutoMapperConfiguration.Configure();
}
}