I cannot find an example of how to do this. I am new to AutoMapper. I may have used the terminology incorrectly.
public class Pet
{
public int petID {get;set;}
public string Name { get; set; }
public string Breed { get; set; }
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Pet> Pets { get; set; }
}
public personVM
{
public string FirstName { get; set; }
public string LastName { get; set; }
List <PetDisplay> PetDisplay {get;set}
}
public PetDisplay
{
int petID {get;set;}
string petDetails {get;set} // This should be a string like Pet.Name & " | " & Pet.Breed
}
how do map from person to personVM? Thanks
You need to set up a mapping from Person → personVM and from Pet → PetDisplay:
Mapper.CreateMap<Person, personVM>()
.ForMember(dest => dest.PetDisplay, opt => opt.MapFrom(src => src.Pets));
Mapper.CreateMap<Pet, PetDisplay>()
.ForMember(
dest => dest.petDetails,
opt => opt.MapFrom(src => string.Format("{0} | {1}", src.Name, src.Breed)));
Example usage:
var person = new Person
{
FirstName = "Jon",
LastName = "Skeet",
Pets = new List<Pet>
{
new Pet { Breed = "Lab", Name = "Fido" }
}
};
personVM vm = Mapper.Map<personVM>(person);
Example: https://dotnetfiddle.net/eL8VyL
PS: I would recommend following the .NET framework naming guidelines and use PascalCase for class and member names (PersonVM instead of personVM).
Related
I have a class for CountryAndCity:
public class CountryAndCity
{
public Country Country { get; set; }
public City City { get; set; }
public ZipCode ZipCode { get; set; }
}
I am using this class in several output classes, for example:
public class OutputClassA
{
public CountryAndCity CountryAndCity { get; set; }
}
public class OutputClassB
{
public CountryAndCity CountryAndCity { get; set; }
}
In addition, i have some "Input Classes" which includes the same relevant fields for mapping with additional other fields:
public class InputClassA : ICountryAndCity
{
...Some other properties.....
public int? CountryId { get; set; }
public string CountryDesc { get; set; }
public int? CityId { get; set; }
public string CityDesc { get; set; }
...Some other properties.....
}
public class InputClassB : ICountryAndCity
{
...Some other properties.....
public int? CountryId { get; set; }
public string CountryDesc { get; set; }
public int? CityId { get; set; }
public string CityDesc { get; set; }
...Some other properties.....
}
i didn't want to duplicate the code for every CreateMap statement for CountryAndCity property mapping for every Input and output combination types so i decided to use an interface that all the "input types" implements.
i created this configuration and its working great if i implement ICountryAndCity on all the relevant "input classes" and using "Mapper.Map" for the interface inside the CreateMap function.
Mapper.Initialize(cfg =>
{
cfg.CreateMap<InputClassA, OutputClassA>()
.ForMember(dest => dest.CountryAndCity,
opts => opts.MapFrom(src => Mapper.Map<ICountryAndCity, CountryAndCity>((ICountryAndCity)src)));
cfg.CreateMap<InputClassB, OutputClassB>()
.ForMember(dest => dest.CountryAndCity,
opts => opts.MapFrom(src => Mapper.Map<ICountryAndCity, CountryAndCity>((ICountryAndCity)src)));
cfg.CreateMap<ICountryAndCity, CountryAndCity>()
.ForMember(dest => dest.Country,
opts => opts.MapFrom(
src => new Country
{
CountryId = src.CountryId,
CountryDesc = src.CountryDesc
}))
.ForMember(dest => dest.City,
opts => opts.MapFrom(
src => new City
{
CityId = src.CityId,
CityDesc = src.CityDesc
}))
.ForMember(dest => dest.ZipCode,
opts => opts.MapFrom(
src => new ZipCode
{
ZipCodeId = src.ZipCodeId,
ZipCodeDesc = src.ZipCodeDesc
}));
}
I am sure that there is other better way to do it using AutoMapper without using interface. Can someone help with that?
Having an issue with version 6.1.1. In the below, the result of the reverse map still has the Company object populated. Per this post, which shows what I am doing below, except they are ignoring a property, and I'm ignoring a complex object.
What am I missing?
CreateMap<Item, ItemViewModel>(MemberList.Destination)
.ReverseMap()
.ForMember(x => x.Company, x => x.Ignore())
;
With AutoMapper 6.1 you could use ForPath instead ForMember to ignore complex objects.
See How to ignore property with ReverseMap for further information.
I see not what is wrong, but here is a running sample:
namespace AutomapperTest2
{
internal class Program
{
#region Methods
private static void Main(string[] args)
{
// Configure the mappings
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ApplicantEducation, ApplicantEducationVM>();
cfg.CreateMap<Applicant, ApplicantVM>().ReverseMap()
.ForMember(x => x.Education, x => x.Ignore());
});
var config = new MapperConfiguration(cfg => cfg.CreateMissingTypeMaps = true);
var mapper = config.CreateMapper();
Applicant ap = new Applicant
{
Name = "its me",
Education =
new ApplicantEducation
{
SomeInt = 10,
SomeString = "sampleString"
}
};
// Map
ApplicantVM apVm = Mapper.Map<Applicant, ApplicantVM>(ap);
Applicant apBack = Mapper.Map<ApplicantVM, Applicant>(apVm);
}
#endregion
}
/// Your source classes
public class Applicant
{
public ApplicantEducation Education { get; set; }
public string Name { get; set; }
}
public class ApplicantEducation
{
public int SomeInt { get; set; }
public string SomeString { get; set; }
}
// Your VM classes
public class ApplicantVM
{
public string Description { get; set; }
public ApplicantEducationVM Education { get; set; }
public string Name { get; set; }
}
public class ApplicantEducationVM
{
public int SomeInt { get; set; }
public string SomeString { get; set; }
}
}
}
The source class has 2 attributes, the target class 3 attributes, mapping, I think in the target class has 1 attributes unchanged, I use NotMapped, but did not succeed, but NotMapped is not the way I want, what do you do?
class AAA
{
public string Name { set; get; }
public string Id { set; get; }
public string Remark { set; get; }
}
class AAAViewModel
{
public string Name { set; get; }
public string Id { set; get; }
}
protected override MapperConfiguration Configuration => new MapperConfiguration(cfg=>
{
cfg.CreateMap<AAA, AAAViewModel>(MemberList.Destination);
cfg.CreateMap<AAAViewModel, AAA>(MemberList.Source);
});
[Fact]
public void test()
{
AAA a = new AAA() { Id = "1", Name = "name1", Remark = "remark1" };
var avm = Mapper.Map<AAAViewModel>(a);
AAA b = new AAA() { Remark = "remakrb" };
b = Mapper.Map<AAA>(avm);
Assert.Equal(avm.Id, "1");
}
The attribute is called IgnoreMap.
I have one object AllDriversDetails that contains data for two driver: First and Second.
public class AllDriversDetails
{
public string FirstDriverId { get; set; }
public string FirstDriverName { get; set; }
public string SecondDriverId { get; set; }
public string SecondDriverName { get; set; }
}
I have to convert AllDriversDetails to ComplexDriversDetails that has two properties of same type
public class ComplexDriversDetails
{
public DriverDetails FirstDriver { get; set; }
public DriverDetails SecondDriver { get; set; }
}
public class DriverDetails
{
public string Id { get; set; }
public string Name { get; set; }
}
Is it possible to do with automapper?
I should be no problem. Try something like this
Mapper.CreateMap<AllDriversDetails, ComplexDriversDetails>()
.ForMember(m => m.FirstDriver, opt => opt.MapFrom(src => new DriverDetails {Id = src.FirstDriverId, Name = FirstDriverName }))
.ForMember(m => m.SecondDriver , opt => opt.MapFrom(src => new DriverDetails {Id = src.SecondDriverId, Name = SecondDriverName }))
You can find more information here: http://cpratt.co/using-automapper-creating-mappings/
Here is what I have where I hope someone can help us out:
class Source
{
string name { get; set; }
Inner { get; set; }
}
class Inner
{
Col A { get; set; }
Col B { get; set; }
}
class Col : IList<ClassX>, IEnunmerable<ClassX>
I need to map class Source to a destination type which has:
class Dest
{
string name { get; set; }
IList<ClassY> A { get; set;}
IList<ClassY> B { get; set;}
}
Now, ClassX and class ClassY share the same properties. ClassY class has a subset of the ClassX primitive properties with the exact same names and types.
Tried all kinds of mappings. Just the ClassX to ClassY map, with the collections, without and with any mapping get no mapping found between or missing configuration between Source and Dest
AutoMapper.Mapper.Map<Source, Dest>(src);
Can someone help me out with the mapping? Thanks in advance.
This question is a few months old, but if you're still looking for an answer, this is what I tried that worked:
class Source
{
public string Name { get; set; }
public Inner Inner { get; set; }
}
class Inner
{
public Col A { get; set; }
public Col B { get; set; }
}
class Col : List<ClassX> { }
class ClassX
{
public int Index { get; set; }
public string Name { get; set; }
public ClassX() : this(0, "") { }
public ClassX(int index, string name)
{
this.Index = index;
this.Name = name;
}
}
class ClassY
{
public int Index { get; set; }
public string Name { get; set; }
public ClassY() : this(0, "") { }
public ClassY(int index, string name)
{
this.Index = index;
this.Name = name;
}
}
class Dest
{
public string Name { get; set; }
public List<ClassY> A { get; set; }
public List<ClassY> B { get; set; }
}
[TestMethod]
public void ComplexTest()
{
Mapper.CreateMap<Source, Dest>()
.ForMember(dest => dest.A, config => config.MapFrom(src => src.Inner.A))
.ForMember(dest => dest.B, config => config.MapFrom(src => src.Inner.B));
Mapper.CreateMap<ClassX, ClassY>();
Source source = new Source
{
Name = "Source",
Inner = new Inner
{
A = new Col
{
new ClassX(1, "First"),
new ClassX(2, "Second"),
new ClassX(3, "Third"),
new ClassX(4, "Fourth"),
},
B = new Col
{
new ClassX(5, "Fifth"),
new ClassX(6, "Sixth"),
new ClassX(7, "Seventh"),
new ClassX(8, "Eighth"),
},
}
};
Dest destination = Mapper.Map<Source, Dest>(source);
Assert.AreEqual(source.Name, destination.Name);
Assert.AreEqual(source.Inner.A.Count, destination.A.Count);
Assert.AreEqual(source.Inner.B.Count, destination.B.Count);
Assert.AreEqual(source.Inner.A[0].Name, destination.A[0].Name);
Assert.AreEqual(source.Inner.B[0].Name, destination.B[0].Name);
}
I didn't go too in-depth with my Asserts, so there may be something I missed, but they appear to be mapped properly.