Issue with a particular type of mapping with classes SourceClass and DestinationClass
public class SourceClass
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<SourceNestedClass> SourceNestedClasses { get; set; }
}
public class SourceNestedClass
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class DestNestedClass
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
}
public class DestinationClass
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<DestNestedClass> Nesteds { get; set; }
}
public DestinationClass MapAutomatically(SourceClass source)
{
Mapper.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.Nesteds, opt => opt.Ignore())
.AfterMap((src, dest) =>
{
dest.Nesteds.Clear();
foreach (var nested in src.SourceNestedClasses )
{
DestNestedClass destNest=new DestNestedClass();
destNest.Id=nested.Id;
destNest.FirstName=nested.FirstName;
destNest.LastName=nested.LastName;
destNest.FullName=nested.FullName;
dest.Nesteds.Add(destNest);
}
});
return Mapper.Map<DestinationClass>(source);
}
Want to avoid manual mapping option in MapAutomatically. In this process need to map each properties.To avoid manual mapping is there any process to use bellow syntax.
Mapper.CreateMap<SourceNestedClass, DestNestedClass>()
.ForMember(dest => dest.FullName, opt => opt.FirstName+opt.LastName);
The syntax is descriptive, for nested class mapping with automapper need to take care parent class and child classes as like following
- mapping parent classes with nested classes
- mapping classes
public class SourceClass
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<SourceNestedClass> SourceNestedClasses { get; set; }
public SourceClass()
{
SourceNestedClasses = new List<SourceNestedClass>();
}
}
public class SourceNestedClass
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class DestNestedClass
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
}
public class DestinationClass
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<DestNestedClass> Nesteds { get; set; }
public DestinationClass()
{
Nesteds = new List<DestNestedClass>();
}
}
class Program
{
public static DestinationClass MapAutomatically(SourceClass sourceInfo)
{
var config = new MapperConfiguration(cfg =>
{
//mapping parent classes with nested classes
cfg.CreateMap<SourceClass, DestinationClass>()
.ForMember(dest => dest.Nesteds, opt => opt.MapFrom(source => source.SourceNestedClasses));
//mapping classes
cfg.CreateMap<SourceNestedClass, DestNestedClass>()
.ForMember(dest => dest.FullName, opt => opt.MapFrom(source => source.FirstName + source.LastName));
});
var mapper = config.CreateMapper();
var destResult = mapper.Map<SourceClass, DestinationClass>(sourceInfo);
return destResult;
}
static void Main(string[] args)
{
var sourceInfo = new SourceClass
{
Id = 5,
Name = "SourceClass",
SourceNestedClasses = { new SourceNestedClass { Id = 10, FirstName = "Test", LastName = "Address" } }
};
var destResult = MapAutomatically(sourceInfo);
}
}
}
Related
There are some classes with relations for me
public class MasterList
{
public int ListId { get; set; }
public string ListName { get; set; }
public int CompanyId { get; set; }
public string Company { get; set; }
public int UniqueId { get; set; }
public DateTime Created { get; set; }
public List<MasterSubList> SubLists { get; set; }
}
public class MasterSubList
{
public int SubListId { get; set; }
public string SubListName { get; set; }
public string Status { get; set; }
public DateTime Created { get; set; }
public List<SubListClick> Clicks { get; set; }
}
public class SubListClick
{
public int ClickId { get; set; }
public string ClickName { get; set; }
}
Can we create a SubList ViewModel by copying all properties from associated MasterList for each of the MasterSubList using AutoMapper?
public class SubListViewModel
{
public int ListId { get; set; }
public string ListName { get; set; }
public int CompanyId { get; set; }
public string Company { get; set; }
public int UniqueId { get; set; }
public DateTime Created { get; set; }
public int SubListId { get; set; }
public string SubListName { get; set; }
public string Status { get; set; }
public DateTime Created { get; set; }
public List<SubListClick> Clicks { get; set; }
}
if my MasterList contain 2 items with 2 MasterSubList each , My resulting SubListViewModel should contain 4 items in total
Can we define automapper mapping against the SubListViewModel based on MasterSubList but include properties from parent MasterList
public class SubListViewModel: IMapFrom<MasterSubList>
{
public int ListId { get; set; }
public string ListName { get; set; }
public int CompanyId { get; set; }
public string Company { get; set; }
public int UniqueId { get; set; }
public DateTime ListCreated { get; set; }
public int SubListId { get; set; }
public string SubListName { get; set; }
public string Status { get; set; }
public DateTime Created { get; set; }
public List<SubListClick> Clicks { get; set; }
public void Mapping(Profile profile)
{
profile.CreateMap<EcastCampaign, ECastRecordsModel>()
.ForMember(d => d.ListId, opt => opt.MapFrom(p => p. ????????? )) how to access Parent object here
.ForMember(d => d.ListName, opt => opt.MapFrom(p => p.?????????))
.ForMember(d => d.CompanyId, opt => opt.MapFrom(p => p.?????????))
.ForMember(d => d.Company, opt => opt.MapFrom(p => p.?????????))
.ForMember(d => d.UniqueId, opt => opt.MapFrom(p => p.))
.ForMember(d => d.ListCreated, opt => opt.MapFrom(p => p.?????????))
}
}
or the mapping should be at some other way?
At present I am doing this conversion by looping through the list
List<SubListViewModel> eRecords = new List<SubListViewModel>();
foreach (MasterList list in apiData)
{
foreach (MasterSubList campign in list.SubLists)
{
SubListViewModel _record = new SubListViewModel();
_record.SubListId = campign.SubListId ;
_record.SubListName = campign.SubListName ;
_record.Status = campign.Status;
_record.CampaignCreated = campign.Created;
_record.Clicks= campign.Clicks;
// now populate parent properties
_record.ListId = list.ListId;
_record.ListName = list.ListName;
_record.CompanyId = list.CompanyId;
_record.Company = list.Company;
_record.UniqueId = list.UniqueId;
_record.ListCreated = list.Created;
eRecords.Add(_record);
}
}
I try to use AutoMapper but when I what to map 2 collection I get an error.
These are my entity and dto classes that I want to use AutoMapper:
public class HeadQuarters
{
public int Id { get; private set; }
public string HeadQuartersName { get; set; }
public string HeadQuartersCode { get; set; }
public string HeadQuartersDescription { get; set; }
public bool IsActiv { get; set; }
public ICollection<Adresa> Adresa { get; set; }
}
public class HeadQuartersDTO
{
public string HeadQuartersName { get; set; }
public string HeadQuartersCode { get; set; }
public string HeadQuartersDescription { get; set; }
public ICollection<AdresaDTO> Addresses { get; set; }
public EntityState Status { get; set; }
}
These are my entity and dto collection classes:
public class AdresaDTO
{
public int Id { get; set; }
public string Street { get; set; }
public string StreetNr { get; set; }
public string Block { get; set; }
public string Entrance{ get; set; }
public string Apartment{ get; set; }
public double? Longitude { get; set; }
public double? Latitude { get; set; }
public int? CityId { get; set; }
public EntityState Status { get; set; }
}
public partial class Adresa
{
public int Id { get; private set; }
public string Street { get; set; }
public string StreetNr { get; set; }
public string Block { get; set; }
public string Entrance{ get; set; }
public string Apartment{ get; set; }
public double? Longitude { get; set; }
public double? Latitude { get; set; }
public int CityId { get; set; }
public int? HeadQuartersId { get; set; }
public int? EmployeeId { get; set; }
public int? ContractPersonDataId { get; set; }
}
I write this code for to use AutoMapper:
public static HeadQuarters DtoToEntity(HeadQuartersDTO dto)
{
var mapper = new Mapper(MapperConfiguration());
return mapper.Map<HeadQuarters>(dto);
}
private static MapperConfiguration MapperConfiguration()
{
return new MapperConfiguration(cfg =>
cfg.CreateMap<HeadQuartersDTO, HeadQuarters>()
.ForMember(dest => dest.Adresa, act => act.MapFrom(src => src.Addresses)));
}
But when I add some in collection I get an error. This is the error message that I get:
If I understand what you’re trying to do, you should be able to update your code like this:
public static HeadQuarters DtoToEntity(HeadQuartersDTO dto)
{
var mapper = new Mapper(MapperConfiguration());
return mapper.Map<HeadQuarters>(dto);
}
private static MapperConfiguration MapperConfiguration()
{
return new MapperConfiguration(cfg =>
cfg.CreateMap<AdresaDTO, Adresa>()
.ForMember(dest => dest.CityId, act => act.MapFrom(src => src.CityId ?? default(int)))
.ForMember(dest => dest.HeadQuartersId, act => act.Ignore())
.ForMember(dest => dest.EmployeeId, act => act.Ignore())
.ForMember(dest => dest.ContractPersonDataId, act => act.Ignore());
cfg.CreateMap<HeadQuartersDTO, HeadQuarters>()
.ForMember(dest => dest.Id, act => act.Ignore())
.ForMember(dest => dest.IsActiv, act => act.Ignore())
.ForMember(dest => dest.Adresa, act => act.MapFrom(src => src.Addresses)));
}
I have an ASP.NET Core application with the following entity classes:
public class CustomerEntity : IAuditableEntity {
private readonly List<AddressEntity> _addresses = new List<AddressEntity>();
public CustomerEntity() {
Id = default;
IsPremierCustomer = false;
}
public int Id { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int CustomerTypeId { get; set; }
public string EmailAddress { get; set; }
public bool IsPremierCustomer { get; private set; }
public CustomerTypeEntity CustomerType { get; }
public IReadOnlyCollection<AddressEntity> Addresses => _addresses;
public void AddAddress(AddressEntity address) {
_addresses.Add(address);
}
public void SetPremierStatus(bool premierCustomer) {
if (IsPremierCustomer == premierCustomer) {
return;
}
IsPremierCustomer = premierCustomer;
}
}
public class CustomerTypeEntity {
public CustomerTypeEntity(string description) {
Id = default;
Description = description;
}
public int Id { get; }
public string Description { get; }
}
public class AddressEntity : IAuditableEntity {
public AddressEntity() {
Id = default;
}
public int Id { get; }
public int CustomerId { get; set; }
public int AddressTypeId { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public int CountryId { get; set; }
public AddressTypeEntity AddressType { get; }
public CountryEntity Country { get; }
}
public class AddressTypeEntity {
public AddressTypeEntity(string description) {
Id = default;
Description = description;
}
public int Id { get; }
public string Description { get; }
}
public class CountryEntity {
public CountryEntity(int numericCode, string alpha2Code, string alpha3Code, string englishName, string frenchName) {
NumericCode = numericCode;
Alpha2Code = alpha2Code;
Alpha3Code = alpha3Code;
EnglishName = englishName;
FrenchName = frenchName;
}
public int NumericCode { get; }
public string Alpha2Code { get; }
public string Alpha3Code { get; }
public string EnglishName { get; }
public string FrenchName { get; }
}
Following are the corresponding DTO classes:
public class CustomerWithAddressDTO {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string CustomerType { get; set; }
public string EmailAddress { get; set; }
public bool IsPremierCustomer { get; set; }
public IEnumerable<AddressDTO> Addresses { get; set; }
}
public class AddressDTO {
public int Id { get; set; }
public string AddressType { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public string Province { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
I have mapping defined as follows:
public class CustomerWithAddressProfile : Profile {
public CustomerWithAddressProfile() {
CreateMap<AddressEntity, AddressDTO>()
.ForMember(dest => dest.AddressType, src => src.MapFrom(x => x.AddressType.Description))
.ForMember(dest => dest.Country, src => src.MapFrom(x => x.Country.Alpha3Code));
CreateMap<CustomerEntity, CustomerWithAddressDTO>()
.ForMember(dest => dest.CustomerType, src => src.MapFrom(x => x.CustomerType.Description))
.ForMember(dest => dest.Addresses, src => src.MapFrom(x => x.Addresses));
}
}
In my code, I fetch the customers including addresses from database and map as below:
[HttpGet]
public ActionResult<IEnumerable<CustomerWithAddressDTO>> GetAllCustomers() {
var customers = _customerWithAddressRepository.FindAll();
var customerDTOs = _mapper.Map<ICollection<CustomerEntity>, IEnumerable<CustomerDTO>>(customers);
return Ok(customerDTOs);
}
The customers are getting populated (mapped) correctly. But the nested addresses are never getting populated. I have searched for a solution but still no luck. Does anyone has any thoughts.
Thanks in advance.
I have a db objects that i would like to map to my view object in my application, but not every property getting mapped.
here is my Automapper set up:
Here is my View class that i would like AutoMapper to map to
public class CustomerDetails
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public DateTime CreateDate { get; set; }
public decimal Balance { get; set; }
public List<Email> Emails { get; set; }
public List<Address> Addresses { get; set; }
public class Email
{
public Guid Id { get; set; }
public string EmailName { get; set; }
}
public class Address
{
public Guid Id { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Country { get; set; }
}
}
Here is db classes:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual CustomerBalance Balance { get; set; }
public virtual ICollection<Email> Emails { get; set; }
public virtual ICollection<Address> Address { get; set; }
public class Email
{
public Guid Id { get; set; }
public string EmailName { get; set; }
public bool IsPrimary { get; set; }
public virtual Customer Customer { get; set; }
}
public class Address
{
public Guid Id { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string Country { get; set; }
}
}
here is how i set up my configuration for AutoMapper
Mapper.Initialize(config =>
{
config.AddProfile<CustomerProfile>();
});
public class CustomerProfile : Profile
{
public CustomerProfile()
{
CreateMap<DataModels.Phone, Phone>();
CreateMap<DataModels.Email, Email>();
CreateMap<DataModels.Address, Address>();
CreateMap<DataModels.CustomerPin, Pin>()
.ForMember(x => x.PinNumber, y => y.MapFrom(s => s.Pin))
.ForMember(x => x.Id, y => y.MapFrom(s => s.Id))
;
CreateMap<Customer, CustomerDetails>()
.ForMember(x => x.Phones, y => y.MapFrom(s => s.Phones))
.ForMember(x => x.Emails, y => y.MapFrom(s => s.Emails))
.ForMember(x => x.Balance, y => y.MapFrom(s => s.Balance.Balance))
.ForMember(x => x.Pins, y => y.MapFrom(s => s.Pin))
.ForMember(x => x.Addresses, y => y.MapFrom(s => s.Address))
;
CreateMap<Customer, CustomerDetails>().ReverseMap();
}
}
The strange thing is is that everything getting mapped as expected, except the Addressesproperty and Balance on my CustomerDetails.cs. The list collection is null even though i specified to map it from a member. However, email List is getting mapped appropriately.
Am I missing something?
I have following database objects:
public class LinkedContact
{
public int LinkedContactID { get; set; }
public Nullable<int> ContactID { get; set; }
public Nullable<int> ContactTypeID { get; set; }
public Nullable<bool> Deleted { get; set; }
public virtual Contact Contact { get; set; }
public virtual ContactType ContactType { get; set; }
}
public class Contact
{
public Contact()
{
this.LinkedContact = new HashSet<LinkedContact>();
}
public int ContactID { get; set; }
public string DisplayName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Nullable<bool> Deleted { get; set; }
public virtual ICollection<LinkedContact> LinkedContact { get; set; }
}
public class ContactType
{
public ContactType()
{
this.LinkedContact = new HashSet<LinkedContact>();
}
public int ContactTypeID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<LinkedContact> LinkedContact { get; set; }
}
I want to map it into following DTO
public class ContactDTO
{
public int ContactID { get; set; }
public string DisplayName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ContactTypeDTO ContactType { get; set; }
}
public class ContactTypeDTO
{
public int ContactTypeID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
So basically, the Contact Type from Linked Contact should map to Contact DTO. End user will only see Contact View Model and is not aware of Linked Contact and hence the structure. Can anyone help me with the mapping configuration. I have tried the following with no luck
CreateMap<Contact, ContactDTO>().ReverseMap();
CreateMap<LinkedContact, ContactDTO>()
CreateMap<ContactType, ContactTypeDTO>().ReverseMap();
look through this link , there is a good sample
CreateMap<LinkedContact, ContactDTO>()
.ForMember(dest => dest.DisplayName, opts => opts.MapFrom(src => src.Contact.DisplayName))
.ForMember(dest => dest.FirstName, opts => opts.MapFrom(src => src.Contact.FirstName))
.ForMember(dest => dest.LastName, opts => opts.MapFrom(src => src.Contact.LastName))
another option:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Contact, ContactDTO>().ReverseMap();
cfg.CreateMap<ContactType, ContactTypeDTO>().ReverseMap();
cfg.CreateMap<LinkedContact, ContactDTO>().ConvertUsing(src =>
{
var contact = Mapper.Map<Contact, ContactDTO>(src.Contact);
contact.ContactType = Mapper.Map<ContactType, ContactTypeDTO>(src.ContactType);
return contact;
});
});
Finally I used the below configuration which mapped both Contact and Contact Type. Leaving it here for people looking for answer to the same thing:
CreateMap<LinkedContact, ContactDTO>().ConvertUsing((src, dest, context) =>
{
dest = context.Mapper.Map<ContactDTO>(src.Contact);
dest.ContactType = context.Mapper.Map<ContactTypeDTO>(src.ContactType);
return dest;
});
CreateMap<Contact, ContactDTO>().ReverseMap();
CreateMap<ContactType, ContactTypeDTO>().ReverseMap();