I have the below models in Asp.net Core Web API project.
public class TestExamReport
{
public string PatientKey { get; set; }
public string OPDiagnosis { get; set; }
public string ORDiagnosis { get; set; }
public OPExam OPExamDetails { get; set; }
public ORExam ORExamDetails { get; set; }
}
public class OPExam
{
public BaselineOP Baseline { get; set; }
public CurrentOP Current { get; set; }
}
public class ORExam
{
public BaselineOR Baseline { get; set; }
public CurrentOR Current { get; set; }
}
public class BaselineOP
{
public string SeriesKey { get; set; }
public DateTime SeriesDate { get; set; }
public string ImagePath { get; set; }
public DateTime? ReviewedOn { get; set; }
}
public class BaselineOR
{
public string SeriesKey { get; set; }
public DateTime SeriesDate { get; set; }
public string ImagePath { get; set; }
public DateTime? ReviewedOn { get; set; }
}
public class CurrentOP : BaselineOP
{
public bool ThresholdFlag { get; set; }
}
public class CurrentOR : BaselineOR
{
public bool ThresholdFlag { get; set; }
}
I have the below model in Data Access Layer:
public class TestExamResult
{
public string Patientkey { get; set; }
public string OPDiagnosis { get; set; }
public string ORDiagnosis { get; set; }
public string BaselineOPSeriesKey { get; set; }
public DateTime BaselineOPSeriesDate { get; set; }
public string BaselineOPImage { get; set; }
public DateTime? BaselineOPReviewedOn { get; set; }
public string CurrentOPSeriesKey { get; set; }
public DateTime CurrentOPSeriesDate { get; set; }
public string CurrentOPImage { get; set; }
public DateTime? CurrentOPReviewedOn { get; set; }
public bool CurrentOPThresholdFlag { get; set; }
public string BaselineORSeriesKey { get; set; }
public DateTime BaselineORSeriesDate { get; set; }
public string BaselineORImage { get; set; }
public DateTime? BaselineORReviewedOn { get; set; }
public string CurrentORSeriesKey { get; set; }
public DateTime CurrentORSeriesDate { get; set; }
public string CurrentORImage { get; set; }
public DateTime? CurrentORReviewedOn { get; set; }
public bool CurrentORThresholdFlag { get; set; }
}
I have below Automapper profile class:
public class PersonProfile : Profile
{
public PersonProfile()
{
CreateMap<TestExamResult, TestExamReport>()
.ForMember(dest => dest.OPExamDetails, src => src.Ignore())
.ForMember(dest => dest.ORExamDetails, src => src.Ignore())
.AfterMap((Src, Dest) =>
Dest.OPExamDetails = new OPExam
{
Baseline = new BaselineOP()
{
SeriesKey = Src.BaselineOPSeriesKey,
SeriesDate = Src.BaselineOPSeriesDate,
ImagePath = Src.BaselineOPImage,
ReviewedOn = Src.BaselineOPReviewedOn
},
Current = new CurrentOP()
{
SeriesKey = Src.CurrentOPSeriesKey,
SeriesDate = Src.CurrentOPSeriesDate,
ImagePath = Src.CurrentOPImage,
ReviewedOn = Src.CurrentOPReviewedOn,
ThresholdFlag = Src.CurrentOPThresholdFlag
}
})
.AfterMap((Src, Dest) =>
Dest.ORExamDetails = new ORExam
{
Baseline = new BaselineOR()
{
SeriesKey = Src.BaselineORSeriesKey,
SeriesDate = Src.BaselineORSeriesDate,
ImagePath = Src.BaselineORImage,
ReviewedOn = Src.BaselineORReviewedOn
},
Current = new CurrentOR()
{
SeriesKey = Src.CurrentORSeriesKey,
SeriesDate = Src.CurrentORSeriesDate,
ImagePath = Src.CurrentORImage,
ReviewedOn = Src.CurrentORReviewedOn,
ThresholdFlag = Src.CurrentORThresholdFlag
}
});
}
}
The above code is working fine as I'm using AfterMap. However, is there any better way of writing this rather than using AfterMap? AfterMap feels like I'm writing mapping code myself rather than using Automapper in a better manner.
I've also tried a different approach to nested object mapping from Automapper documentation. However, it is not working in my case and I'm getting one or the other error.
Edit:
I have tried below mapping as well, but the TestExamReport objects are null and only PatientKey is having value.
CreateMap<TestExamResult, TestExamReport>();
//Below two lines don't have impact, even
//If they are remove, objects are still null
CreateMap<TestExamResult, OPExam>();
CreateMap<TestExamResult, ORExam>();
CreateMap<TestExamResult, BaselineOP>()
.ForMember(dest => dest.SeriesKey, src => src.MapFrom(y => y.BaselineOPSeriesKey))
.ForMember(dest => dest.SeriesDate, src => src.MapFrom(y => y.BaselineOPSeriesDate))
.ForMember(dest => dest.ImagePath, src => src.MapFrom(y => y.BaselineOPImage))
.ForMember(dest => dest.ReviewedOn, src => src.MapFrom(y => y.BaselineOPReviewedOn))
.ReverseMap();
CreateMap<TestExamResult, CurrentOP>()
.ForMember(dest => dest.SeriesKey, src => src.MapFrom(y => y.CurrentOPSeriesKey))
.ForMember(dest => dest.SeriesDate, src => src.MapFrom(y => y.CurrentOPSeriesDate))
.ForMember(dest => dest.ImagePath, src => src.MapFrom(y => y.CurrentOPImage))
.ForMember(dest => dest.ReviewedOn, src => src.MapFrom(y => y.CurrentOPReviewedOn))
.ForMember(dest => dest.ThresholdFlag, src => src.MapFrom(y => y.CurrentOPThresholdFlag))
.ReverseMap();
CreateMap<TestExamResult, BaselineOR>()
.ForMember(dest => dest.SeriesKey, src => src.MapFrom(y => y.BaselineORSeriesKey))
.ForMember(dest => dest.SeriesDate, src => src.MapFrom(y => y.BaselineORSeriesDate))
.ForMember(dest => dest.ImagePath, src => src.MapFrom(y => y.BaselineORImage))
.ForMember(dest => dest.ReviewedOn, src => src.MapFrom(y => y.BaselineORReviewedOn))
.ReverseMap();
CreateMap<TestExamResult, CurrentOR>()
.ForMember(dest => dest.SeriesKey, src => src.MapFrom(y => y.CurrentORSeriesKey))
.ForMember(dest => dest.SeriesDate, src => src.MapFrom(y => y.CurrentORSeriesDate))
.ForMember(dest => dest.ImagePath, src => src.MapFrom(y => y.CurrentORImage))
.ForMember(dest => dest.ReviewedOn, src => src.MapFrom(y => y.CurrentORReviewedOn))
.ForMember(dest => dest.ThresholdFlag, src => src.MapFrom(y => y.CurrentORThresholdFlag))
.ReverseMap();
I've resolved the issue from this and this.
Below is my sample code to make it work:
cfg.CreateMap<TestExamResult, BaselineOP>()
.ForMember(d => d.SeriesKey, opt => opt.MapFrom(src => src.BaselineOPSeriesKey))
.ForMember(d => d.SeriesDate, opt => opt.MapFrom(src => src.BaselineOPSeriesDate))
.ForMember(d => d.ImagePath, opt => opt.MapFrom(src => src.BaselineOPImage))
.ForMember(d => d.ReviewedOn, opt => opt.MapFrom(src => src.BaselineOPReviewedOn))
.ReverseMap();
cfg.CreateMap<TestExamResult, BaselineOR>()
.ForMember(d => d.SeriesKey, opt => opt.MapFrom(src => src.BaselineORSeriesKey))
.ForMember(d => d.SeriesDate, opt => opt.MapFrom(src => src.BaselineORSeriesDate))
.ForMember(d => d.ImagePath, opt => opt.MapFrom(src => src.BaselineORImage))
.ForMember(d => d.ReviewedOn, opt => opt.MapFrom(src => src.BaselineORReviewedOn))
.ReverseMap();
cfg.CreateMap<TestExamResult,OPExam>()
.ForMember(d=>d.BaselineOP, opt => opt.MapFrom(src => src)).ReverseMap();
cfg.CreateMap<TestExamResult,ORExam>()
.ForMember(d=>d.BaselineOR, opt => opt.MapFrom(src => src)).ReverseMap();
cfg.CreateMap<TestExamResult, TestExamReport>()
.ForMember(d=>d.OPExam, opt => opt.MapFrom(src => src))
.ForMember(d=>d.ORExam, opt => opt.MapFrom(src => src))
.ReverseMap();
The only problem I'm facing right now with the above code is that if all the property values are null, for example, for BaselineOP, I want to set it to null. I need to explore Automapper more for that.
EDIT:
After going through this post, I was able to mark BaselineOP as null if all its properties are null. It is working.
cfg.CreateMap<TestExamResult,OPExam>()
.ForMember(d=>d.BaselineOP, b => b.MapFrom((c, a, obj, context) => !string.IsNullOrEmpty(c.BaselineOPSeriesKey) ? context.Mapper.Map<BaselineOP>(c) : null))
.ReverseMap();