Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I am facing issue for mapping for nested objects using Auto Mapper method
Can any one give suggestion to map Source and Target class using auto mapper
For example this is sample code.
Source:
Main Class:
public class EMP {
public int empid {get;set;}
public int Name {get;set;}
public EMPDetails Employeedata {get;set;}//Here is inner object in main class
public EmpContact EmpContactdetails {get;set;}//Here is other inner object in main class
public Class EMPDetails {
public String Name {get;set;}
public EmpAdd EmpAddress {get;set;}//Here is inner Object in one class
public class EmpAdd {
public int id {get;set;}
public int Street {get;set;}
public class EmpContact {
public int id {get;set;}
public int Mobile {get;set;}
Target:
Main Class:
public class EMPInfo {
public int id {get;set;}
public int EmpName {get;set;}
public EMPPerdata Employeedata {get;set;}//Here is inner object in main class
public EmpContact EmpContactdetails {get;set;}//Here is other inner object in main class
public class EMPPerdata {
public String FullName {get;set;}
public EmpAdressInfo EmpAddress {get;set;}//Here is inner Object in one class
public class EmpAdressInfo {
public int id {get;set;}
public int Street {get;set;}
public class EmpContact {
public int id {get;set;}
public int Mobile {get;set;}
Edit (because that's not a great answer)
So, just wanted to add on this edit to show a few AutoMapper best practices because if you follow those best practices it's a lot easier to use.
AutoMapper Profiles
When using Automapper, unless you are mapping really really simple objects, the best way to set up your mapping is through using profiles. To use those profiles make certain to add a using AutoMapper;
to your program and then you can create a mapping profile like so:
public class MappingProfile : Profile
public MappingProfile()
CreateMap<EMP, EMPInfo>();
Now, in any of the classes you want to use this profile you can use it like so:
Mapper.Initialize(cfg =>
cfg.AddProfile<MappingProfile>();
EMPInfo empInfo = Mapper.Map<EMP, EMPInfo>(emp);
Now... why would you ever go to all of the trouble to do this? You could have just as easily said Mapper.CreateMap<EMP, EMPInfo>(); Mapper.Map<EMP, EMPInfo(src);
and it would be doing the same thing.
The benefits to doing it the way I stated above are three-fold.
Centralization of your mapping expressions. In my case, I usually have a single MappingProfiles class that holds all the Mapping profiles that I could use. This practice helps more to organize your code than anything else.
Reusability. Wherever in your program you need to use that mapping profile which will likely be more than just a single CreateMap()
line you can just initialize that profile and then use it.
Unit Testing. Loading in profiles makes unit testing for AutoMapper really easy. And, unit testing will help you figure out exactly how to map nested objects.
Unit Testing AutoMapper
In your unit testing project (add one if you don't have it, it's a default project template in visual studio) you should have a class that holds the following unit test:
[TestMethod]
public void AutoMapperConfigIsValid()
Mapper.Initialize(cfg =>
cfg.AddProfile<MappingProfile>();
// add all profiles you'll use in your project here
Mapper.AssertConfigurationIsValid();
Now, if I were to run that unit test using the classes you laid out above and the mapping profile that I put above it will give me the error:
Unmapped Properties:
EmpName
This isn't the full error, just the most important part. What's happening is... AutoMapper cannot figure out where the id
and EmpName
fields on the EMPInfo Type should be mapped from.
To resolve this error we need to add mapping for particular members to our profile. Our profile becomes:
CreateMap<Source.EMP, Target.EMPInfo>()
.ForMember(dest => dest.id, opt => opt.MapFrom(src => src.empid))
.ForMember(dest => dest.EmpName, opt => opt.MapFrom(src => src.Name));
We add that in... run the test again... get a new error.
Add a custom mapping expression, ignore, add a custom resolver, or modify the destination type TestStuff.Target.EmpContact.
Context:
Mapping from type TestStuff.Source.EmpContact to TestStuff.Target.EmpContact
Exception of type 'AutoMapper.AutoMapperConfigurationException' was thrown.
This tells us that we need to add in a map for the nested members of the objects we are mapping.
To resolve this, we add the following map to the mapping profile:
CreateMap<Source.EmpContact, Target.EmpContact>();
Now what you need to do here, and this is sort of an arduous, but necessary, process, is keep running that configuration test and fixing the issues that it gives you until the test does not fail.
When all the issues are fixed, the mapping profile looks like this:
public class MappingProfile : Profile
public MappingProfile()
CreateMap<Source.EMP, Target.EMPInfo>()
.ForMember(dest => dest.id, opt => opt.MapFrom(src => src.empid))
.ForMember(dest => dest.EmpName, opt => opt.MapFrom(src => src.Name));
CreateMap<Source.EmpContact, Target.EmpContact>();
CreateMap<Source.EMPDetails, Target.EMPPerdata>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(src => src.Name));
CreateMap<Source.EmpAdd, Target.EmpAdressInfo>();
This mapping profile works great and will map your two objects fine.
Now, this map seem to be a lot of work for a little thing, but the benefits of doing it this way come with scale. If you are ever using AutoMapper in a large 'Adapter' type project, code structured this way is going to be easier to navigate, read and test.
Hopefully this helps a bit. Sorry if I went way too far at any point here but hopefully this answer can help anyone trying to use AutoMapper.
You can find documentation on some of the stuff I mentioned above in the AutoMapper documentation as well: https://github.com/AutoMapper/AutoMapper/wiki/Configuration
Mapper.CreateMap<EMP,EmpInfo>();
Mapper.CreateMap<EmpDetails,EMPPerdata>();
Mapper.CreateMap<EmpContact,EmpContact>();
Mapper.CreateMap<EmpAdd,EmpAdressInfo>();
then:
Mapper.Map<Emp, EmpInfo>(someEmp);
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.