I have a situation there where I get some data about trips from an API. I'm using AutoMapper to map this "API model" to an EF Core entity for storing in my SQL Server database.
Most of the mappings are straightforward, but I'm struggling with one situation: the TripModel
has a property called ReasonForTravel
which is an int?
value - if it has a value, and that value is > 0
, then I want to use a custom ValueConverter
to convert that int
to a string that I need - but if either the ReasonForTravel
has no value at all, or it's <= 0
, then I want to instead take the value from CustomTravelReason
on the TripModel
.
How do I express this in an AutoMapper CreateMap
so that I can map my TripModel
to Trip
entity in one step?
Here's my code - the model, the entity, and the AutoMapper Profile
:
public class TripModel
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public int? ReasonForTravel { get; set; }
public string CustomTravelReason { get; set; }
// more stuff, but irrelevant here
}
public class Trip
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string ReasonForTrip { get; set; }
}
public class TripProfile : Profile
{
public TripProfile()
{
CreateMap<TripModel, Trip>
// I know these two aren't strictly necessary - just for illustration of what I'm doing
.ForMember(dest => dest.Firstname, opt => opt.MapFrom(src => src.Firstname))
.ForMember(dest => dest.Lastname, opt => opt.MapFrom(src => src.Lastname))
// but how do I specify this now?? This is for the case of ReasonForTravel > 0
.ForMember(dest => dest.ReasonForTrip, opt => opt.ConvertUsing(new TravelReasonConverter(), src => src.Lastname))
// and this is for the case of ReasonForTravel <= 0 or ReasonForTravel = null
.ForMember(dest => dest.ReasonForTrip, opt => opt.MapFrom(src => src.CustomTravelReason));
}
}
There's a MapFrom
overload that allows to pass a Func
into which you can specify a if/else check. Unfortunately that can't be combined with ConvertUsing
, but you can just call that converter yourself.
Alternatively you choose to use a regular function to do the conversion instead of using a converter.
CreateMap<TripModel, Trip>()
// Other mappings
// ...
.ForMember(dest => dest.ReasonForTrip,
opt => opt.MapFrom((src, dest, member, resolutionContext) =>
src.ReasonForTravel > 0
? new TravelReasonConverter().Convert(src.ReasonForTravel, resolutionContext)
// or call a function returning a string.
: src.CustomTravelReason
));
public class TravelReasonConverter : IValueConverter<int?, string>
{
public string Convert(int? sourceMember, ResolutionContext context)
=> "some converted value";
}