complete
branch or actively code along using the incomplete code in the master
branch.global.json
file in the route of the solution.> dotnet --list-sdks
TestDrivenAutoMapping.Tests/MappingsTests.cs
you should see the following code:[TestFixture] public class MappingsTests { [OneTimeSetUp] [Obsolete] public void Init() { Mapper.Initialize(cfg => { cfg.AddProfile<Mappings>(); }); } [Test] public void Map_Should_MapPersonToPersonViewModel() { Mapper.AssertConfigurationIsValid(); var entity = new Person(); var vm = Mapper.Map<PersonViewModel>(entity); Assert.NotNull(vm); Assert.IsInstanceOf(typeof(PersonViewModel), vm); } [Test] public void Map_Should_MapPersonViewModelToPerson() { Mapper.AssertConfigurationIsValid(); var vm = new PersonViewModel(); var entity = Mapper.Map<Person>(vm); Assert.NotNull(vm); Assert.IsInstanceOf(typeof(Person), entity); }
Mapper.AssertConfigurationIsValid();
method call. This is what will help us to create the correct mappings.TestDrivenAutoMapping.Common/Mappings/Mappings.cs
file and should have the following content in the default constructor of the Mappings
class:public Mappings() { CreateMap<PersonViewModel, Person>(); CreateMap<Person, PersonViewModel>(); ... }
Profile
. The two private methods found in the same class are custom Type Convertors that convert a string
to DateTime
and vice versa. We won't need to worry about these as they are just another type of mapping.Person
to PersonViewModel
.Mapping.cs
would be sufficient and our Mapper.AssertConfigurationIsValid();
test method call in would pass. CreateMap<PersonViewModel, Person>().ReverseMap();
IList<string> Jobs { get; set; }
, in the ViewModel that is of no relevance to the domain model.PersonViewModel -> Person (Destination member list) TestDrivenAutoMapping.Common.ViewModels.PersonViewModel -> TestDrivenAutoMapping.Common.Models.Person (Destination member list) Unmapped properties: AddressId Address JobId Job ============================================================== Person -> PersonViewModel (Destination member list) TestDrivenAutoMapping.Common.Models.Person -> TestDrivenAutoMapping.Common.ViewModels.PersonViewModel (Destination member list) Unmapped properties: HouseName JobViewModel Jobs
TestDrivenAutoMapping.Common/Mappings/Mappings.cs
file as shown below:CreateMap<PersonViewModel, Person>() .ForMember(e => e.Job, opts => opts.MapFrom(src => src.JobViewModel)) .ForMember(e => e.Address, opts => opts.MapFrom(model => model)) .ForMember(e => e.Id, opts => opts.Ignore()) .ForMember(e => e.JobId, opts => opts.Ignore()) .ForMember(e => e.AddressId, opts => opts.Ignore()); CreateMap<Person, PersonViewModel>() .ForMember(e => e.HouseName, opts => opts.MapFrom(src => src.Address.HouseName)) .ForMember(e => e.JobViewModel, opts => opts.MapFrom(src => src.Job)) .ForMember(e => e.Jobs, opts => opts.Ignore());
.ForMember(e => e.Job, opts => opts.MapFrom(src => src.JobViewModel))
, we have specified that this is mapping between two models. Therefore we will need to declare this mapping like so:CreateMap<JobViewModel, Job>();
JobViewModel -> Job (Destination member list) TestDrivenAutoMapping.Common.ViewModels.JobViewModel -> TestDrivenAutoMapping.Common.Models.Job (Destination member list) Unmapped properties: Id
JobViewModel
doesn't have a property called Id
we will want to just ignore this. Update the code like so:CreateMap<JobViewModel, Job>() .ForMember(e => e.Id, opts => opts.Ignore()) .ReverseMap();
ReverseMap()
feature. .ForMember(e => e.Address, opts => opts.MapFrom(model => model))
on the CreateMap<PersonViewModel, Person>()
map. This requires us to define a mapping between Person
and Address
. We also need to define a mapping between the PersonViewModel
and Address
to complete the reverse mapping. Add the following mapping to the Mappings
class:CreateMap<Person, Address>() .ForMember(e => e.HouseName, opts => opts.MapFrom(src => src.Address.HouseName)); CreateMap<PersonViewModel, Address>() .ForMember(e => e.HouseName, opts => opts.MapFrom(src => src.HouseName));
Mappings
class.