Map some properties from TSource to TDestination without losing old other TDestination object properties values using Automapper

Viewed 163

please I'm working on an Asp.Net core project targeted .Net 5 with Clean architecture.

I have this Entity in the Core layer

Exam Entity:

public class Exam : IExam
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    [Required]
    public DateTime ExamDate { get; set; }

    [Required]
    public TimeSpan ExamTime { get; set; }

    [Required]
    public decimal DurationByHour { get; set; }

    [Required]
    public string GroupId { get; set; }

    [Required]
    public string SchoolSubjectId { get; set; }

    [Required]
    public string ProfId { get; set; }

    public virtual Group                 Group         { get; set; }
    public virtual SchoolSubject         SchoolSubject { get; set; }
    public virtual Prof                  Prof          { get; set; }
    public virtual ICollection<ExamMark> ExamMarks     { get; set; }

    public string   CreatedBy    { get; set; }
    public DateTime CreatedOn    { get; set; }
    public bool     IsEdited     { get; set; }
    public string   LastEditor   { get; set; }
    public DateTime LastEditDate { get; set; }
}

And I have this View Model (For edit) an Exam object

ExamEditVm View model/DTO:

public class ExamEditVm
{
    public int         Id             { get; set; }
    public DateTime    ExamDate       { get; set; }
    public TimeSpan    ExamTime       { get; set; }
    public decimal     DurationByHour { get; set; }
    public string      GroupId        { get; set; }
    public List<Group> Groups         { get; set; }
}

Good, now when a user does some Edits in the Edit view and submit the result, another Edit Action result in HTTPPOST will receive the edits as ExamEditVm object. At this point the action should select the Exam who should be edited and using MappingProfile the action will map the ExamEditVm object to selected Exam object

Mapping Profile between Exam and ExamEditVm:

CreateMap<Exam , ExamEditVm>().ReverseMap();

The HttpPost Edit Action Result:

    public async Task<IActionResult> Edit(ExamEditVm model)
            {
                if (ModelState.IsValid)
                {
                    var exam = await _examRepository.GetByIdAsync( model.Id );
                    exam = _mapper.Map<Exam>( model);
                    exam.WriteEditingAudit( _appUser );
    
                    await _examRepository.UpdateAsync( record : exam );
                    await _uow.CommitAsync();
    
                    return RedirectToAction( nameof( Edit ) , new {model.Id} );
                }
// Some logic
            }

What is exactly the problem? The problem is in this line

exam = _mapper.Map<Exam>( model);

When mapping from ExamEditVm to Exam the exam will lost all not mapped properties values because he got another object value. So how can I map from ExamEditVm to Exam and keep the exam object old not mapped properties values after mapping using Automapper and MappingProfile ?

I wish you understand the issue. So please any solution for his problem.

1 Answers

By doing a exam = _mapper.Map<Exam>(model); you are actually creating a new Exam instance, with only the data present in the ExamEditVm model.

What you want to do, is to apply/map the data from the ExamEditVm model object upon the existing Exam exam object.
For this, you have to use the Map overload passing both the source and target object:

_mapper.Map(model, exam);
Related