Reputation: 217
I am using Automapper 6.2.2 and I'm trying to set it up in a Web App. I am trying to use the static Automapper.Initialize()
method placed directly in my Global.asax file.
public class WebApiApplication : HttpApplication
{
protected void Application_Start()
{
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.AllowNullCollections = true;
cfg.CreateMap<LoadArea, LoadAreaWithoutPlannedSlotDto>();
cfg.CreateMap<LoadArea, LoadAreaDto>();
cfg.CreateMap<LoadAreaForCreationDto, LoadArea>().Ignore(d => d.Slots);
cfg.CreateMap<LoadArea, LoadAreaForUpdateDto>();
cfg.CreateMap<LoadAreaForUpdateDto, LoadArea>().ForMember(m => m.Code, i => i.UseDestinationValue());
cfg.CreateMap<PlannedSlot, PlannedSlotDto>();
cfg.CreateMap<PlannedSlotForCreationDto, PlannedSlot>().Ignore(d => d.Area);
cfg.CreateMap<PlannedSlotForUpdateDto, PlannedSlot>();
cfg.CreateMap<UserToReturnDto, User>();
cfg.CreateMap<LoadAreaSlotDetailForReturnDto, LoadAreaSlotDetail>();
});
AreaRegistration.RegisterAllAreas();
UnityConfig.RegisterComponents();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
The strange issue is that while this code runs at startup, the mappings are created but none of them are actually configured.
So if I try to Ignore a property in the Mapper.Initialize(...)
method, it doesn't work and I get an error when the unmapped property is run into when mapping occurs.
I tried using:
cfg.CreateMap<LoadAreaSlotDetailForReturnDto, LoadAreaSlotDetail>().ForMember(d => d.LoadArea, opt => opt.Ignore());
Also tried:
cfg.CreateMap<LoadAreaSlotDetailForReturnDto, LoadAreaSlotDetail>(MemberList.None);
And a few other combinations, including an extension method that would ignore all unmapped members:
public static IMappingExpression<TSource, TDestination> Ignore<TSource, TDestination>(this IMappingExpression<TSource, TDestination> map,
Expression<Func<TDestination, object>> selector)
{
map.ForMember(selector, config => config.Ignore());
return map;
}
But what does work is if I try to Ignore the property Inline in my controller as follows:
[HttpPost]
[Route("{loadAreaId}/details")]
public IHttpActionResult AddLoadAreaSlotDetails([FromUri] string loadAreaId, [FromBody] LoadAreaSlotDetailForAddDto loadAreaSlotDetails)
{
var loadAreaSlotDetailEntity = Mapper.Map<LoadAreaSlotDetailForAddDto, LoadAreaSlotDetail>(loadAreaSlotDetails, opt => opt.ConfigureMap().ForMember(d => d.LoadArea, o => o.Ignore()));
_repo.AddLoadAreaSlotDetail(loadAreaSlotDetailEntity);
return Ok();
}
This proves to me that the Ignore works but at the same time I assume that I'm Initializing and configuring my mappings wrongly but I don't know why because many other examples are Initializing in the same way using the static API. I'm doing the same in a .NET Core project (in the ConfigureServices method) and mappings work, it also ignores unmapped properties by default.
Why does this happen ?
Upvotes: 1
Views: 1425
Reputation: 876
Have you tried using AutoMapper Profiles?
I was then able to configure this in the Startup.cs of my WebApi application. I was using SimpleInjector as my Container:
var profiles =
Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(t => typeof(Profile).IsAssignableFrom(t))
.ToList();
Mapper.Initialize(
mp =>
{
var mapperConfiguration = new MapperConfiguration(cfg => cfg.AddProfiles(profiles));
var mapper = mapperConfiguration.CreateMapper();
container.Register(() => mapper, Lifestyle.Scoped);
});
You then need to define one or more profiles depending on how you want to split out your auto mapper config.
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserDetails, UserTransferObject>();
CreateMap<UserAndAccountDetails, UserAndAccountTransferObject>();
CreateMap<User, UserAndAccountTransferObject>()
.ForMember(
dest => dest.DifferentPropertyName,
orig => orig.MapFrom(src => src.OriginalPropertyName));
}
}
Upvotes: 3