Hi I have been using AutoMapper to convert my objects, and now I'm trying to merge two nested objects into one, but I can't figure out how to do it.
I have the following code:
These are my source objects
class SourceSubItemA
{
string subPropertyA;
}
class SourceSubItemB
{
string subPropertyB;
}
class Source
{
SourceSubItemA subItemA;
SourceSubItemB subItemB;
}
Destination objects
class DestinationSubItem
{
string propertyA;
string propertyB;
}
class Destination
{
DestinationSubItem destItem;
}
This is my Automapper configuration
Mapper.CreateMap<SourceSubItemA, DestinationSubItem>()
.ForMember(dest => propertyA, opt => opt.MapFrom(src => src.subPropertyA));
Mapper.CreateMap<SourceSubItemB, DestinationSubItem>()
.ForMember(dest => propertyB, opt => opt.MapFrom(src => src.subPropertyB));
// Probably I have to do something more here.
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.destItem, opt => opt.MapFrom(src => src.subItemA));
And finally I'm using the mapper by this way
Mapper.Map<Destination>(sourceObject);
The expected result must be a Destination object with a subitem with both properties filled.
Please Help!
As I can see, Destination is just a wrapper of DestinationSubItem that is the one that really needs to get the values from Source.
In that case, you could define a mapper from Source to Destination that puts in dest.destItem the result of mapping from Source directly to DestinationSubItem.
Here an example:
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.destItem, opt => opt.MapFrom(src => Mapper.Map<DestinationSubItem>(src));
Mapper.CreateMap<Source, DestinationSubItem>()
.ForMember(dest => dest.propertyA, opt => opt.MapFrom(src => src.subItemA.subPropertyA)
.ForMember(dest => dest.propertyB, opt => opt.MapFrom(src => src.subItemB.subPropertyB);
Related
I have 6 properties in C Class and I want to map 3 of my properties from A method with output class A and 3 others from B method with output Class B
First, I map A to C (which is defined at MappingProfile class and 3 other properties are ignored) and then I map B to C (which has been defined like previous one)
My problem is that in the second Map my c object is always going to be override with b object and 3 other properties (which I got them from a object) come back as null (because they don't exist in B class).
In the end, I want to Have all data from a and b objects in my c object.
Mapping operations -
Adaptee Amethod = new Adaptee();
List<A> a = Amethod.A().ToList();
List<B> b = Amethod.B().ToList();
List<C> c1 = _mapper.Map<List<A>, List<C>>(a);
List<C> c = _mapper.Map(b, c1);
Mapping profiles -
public MappingProfile()
{
CreateMap<A, C>()
.ForMember(z => z.FN, opt => opt.MapFrom(x => x.FN))
.ForMember(z => z.LN, opt => opt.MapFrom(x => x.LN))
.ForMember(z => z.uniqe, opt => opt.MapFrom(x => x.uniqe))
.ForMember(z => z.Addr, opt => opt.Ignore())
.ForMember(z => z.HomeTown, opt => opt.Ignore())
.ForMember(z => z.NID, opt => opt.Ignore());
CreateMap<B, C>()
.ForMember(z => z.Addr, opt => opt.MapFrom(x => x.Addr))
.ForMember(z => z.HomeTown, opt => opt.MapFrom(x => x.HomeTown))
.ForMember(z => z.NID, opt => opt.MapFrom(x => x.NID))
.ForMember(z => z.FN, opt => opt.Ignore())
.ForMember(z => z.LN, opt => opt.Ignore())
.ForMember(z => z.uniqe, opt => opt.Ignore());
}
I'm using AutoMapper.Extensions.Microsoft.DependancyInjection v8.1.0.
you can use this method for multipli Object
services.AddSingleton(provider => new MapperConfiguration(cfg =>
{
cfg.AddProfile(new sampleProfileMapper());
}).CreateMapper());
I have a customer object with a collection of addresses that I would like to map to a customer view model with a single address view model. The address from the collection that I want to map to the view model is selected by a specific value in the address. i.e. where type Id == 1
My Automapper config is:
cfg.CreateMap<Customer, CustomerVM>()
.ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.Type.Id== 2).FirstOrDefault())
.ReverseMap();
cfg.CreateMap<Address, AddressVM>()
.ForMember(dest => dest.Street,opt=>opt.MapFrom(src=>src.Street1))
.ForMember(dest => dest.State,opt=>opt.MapFrom(src=>src.Region))
.ForMember(dest => dest.Postal, opt => opt.MapFrom(src => src.PostalCode))
public class Customer{
public virtual ICollection<Address> Addresses{get; set;}
}
public class CustomerVM{
public AddressVM Address{get; set;}
}
This is mapping but the address is null.
Is there a way to select a specific object from a collection and map it to single object.
This works for me.
cfg.CreateMap<Customer, CustomerVM>()
.ForMember(dest => dest.Address, address => address
.MapFrom(src => src.Addresses.FirstOrDefault(add => add.Type.Id == 2)));
Nicely it won't throw or map if there is no address.type == 2
I have a automapper mapping that work's just fine , I just don't know if I'll have to re-write it everytime I need to map my model to my viewModel vice-versa. I wonder if there is a way where once it is mapped, automapper knows what to do.
I could create static methods with the mappings in one "helper" class, but I don't know if it is the right approach.
Here is the mapping.
var ax =
new MapperConfiguration(cfg =>
{
cfg.CreateMap<Pessoa, PessoaViewModel>()
.ForMember(dest => dest.cod_endereco, opt => opt.MapFrom(src => src.endereco.codigo))
.ForMember(dest => dest.logradouro, opt => opt.MapFrom(src => src.endereco.logradouro))
.ForMember(dest => dest.cod_tipolograd, opt => opt.MapFrom(src => src.endereco.tipo.codigo))
.ForMember(dest => dest.cod_munic_ender, opt => opt.MapFrom(src => src.endereco.municipio.codigo))
.ForMember(dest => dest.nome_munic_ender, opt => opt.MapFrom(src => src.endereco.municipio.nome))
.ForMember(dest => dest.numero, opt => opt.MapFrom(src => src.endereco.numero))
.ForMember(dest => dest.complemento, opt => opt.MapFrom(src => src.endereco.complemento))
.ForMember(dest => dest.cep, opt => opt.MapFrom(src => src.endereco.cep))
.ForMember(dest => dest.bairro, opt => opt.MapFrom(src => src.endereco.bairro))
;
}).CreateMapper().Map<Pessoa, PessoaViewModel>(p);
If I use the mapping like below:
new MapperConfiguration(cfg => cfg.CreateMap<Pessoa, PessoaViewModel>()).CreateMapper().Map<Pessoa, PessoaViewModel>(p);
the fields that I used forMember method to map them, stays null.
I want to ignore some mappings while I call the Map function.
Here's where I create my Map:
Mapper.CreateMap<User, UserViewModel>()
.ForMember(dest => dest.WebLicenseCount, opt => opt.MapFrom(src => GetCount(src, "0801")))
.ForMember(dest => dest.MobileLicenseCount, opt => opt.MapFrom(src => GetCount(src, "0901")))
.ForMember(dest => dest.ExcelAddInLicenseCount, opt => opt.MapFrom(src => GetCount(src, "0895")))
.ForMember(dest => dest.NextExpirationDate, opt => opt.MapFrom(src => src.Licences.Min(l => l.LicenceProducts.Min(lp => lp.ExpirationDate))))
.ForMember(dest => dest.Licences, opt => opt.MapFrom(src => src.Licences.ToList()))
.ForMember(dest => dest.TicketsCount, opt => opt.MapFrom(src => src.Tickets.Count(t => t.Status != (int)TicketStatusType.Closed)))
.ForMember(dest => dest.ParentContact, opt => opt.MapFrom(src => src.Contact))
.ForMember(dest => dest.ParentUser, opt => opt.MapFrom(src => src.User2))
.ForMember(dest => dest.Contacts, opt => opt.MapFrom(src => src.Contacts))
.ForMember(dest => dest.MainContact, opt => opt.Ignore())
.ForMember(dest => dest.SessionID, opt => opt.Ignore())
;
In my controller I do this:
users = Mapper.Map<UserViewModel[]>(response.users);
I want to ignore in this call, the mapping for those proprieties :WebLicenseCount, MobileLicenseCount, ExcelAddInLicenseCount.
There's anyway to do this?
If this is something you want to do only once then overwrite the mentioned properties in users with the corresponding response.users after the Map() function. If this is something you would want to do often then it means you either need to change your mapping or create a second type (e.g. SpecialUser) for those situations and define different set of mappings for this type.
I have the following classes
Source:
public class NewBusinessSubmission
{
//other properties
public int? TermTypeId { get; set; }
}
Destination:
NewBusinessSubmission class inherits from the PolicyTransaction class shown below (yes it is VB.NET):
<System.Serializable()> Public MustInherit Class PolicyTransaction
Inherits Framework2.BusinessBase(Of PolicyTransaction)
Implements IDisposable
...........
Public Property TermTypeId() As Nullable(Of Integer)
Get
CanReadProperty(True)
If Not _PolicyTermsDataRow.IsTermTypeIdNull Then
Return Me._PolicyTermsDataRow.TermTypeId
End If
End Get
Set(ByVal value As Nullable(Of Integer))
If Nullable(Of Integer).Equals(value, Me.TermTypeId) Then Exit Property
CanWriteProperty(True)
If value.HasValue Then
Me._PolicyTermsDataRow.TermTypeId = value.Value
Else
Me._PolicyTermsDataRow.SetTermTypeIdNull()
End If
AfterTermTypeIdChanged()
Me.PropertyHasChanged()
End Set
End Property
...........
End Class
Mapping Configuration below does not set the TermTypeId:
Mapper.CreateMap<NewBusinessSubmission, NewBusiness>()
.ForMember(x => x.PolicyTxnNum, opt => opt.Ignore())
.ForMember(x => x.ContactProducerLicId, opt => opt.Ignore())
.ForMember(x => x.PolicyNames, opt => opt.Ignore())
.ForMember(x => x.PolicyExp, opt => opt.Ignore());
This one does not work either:
Mapper.CreateMap<NewBusinessSubmission, NewBusiness>()
.ForMember(x => x.PolicyTxnNum, opt => opt.Ignore())
.ForMember(x => x.ContactProducerLicId, opt => opt.Ignore())
.ForMember(x => x.PolicyNames, opt => opt.Ignore())
.ForMember(x => x.PolicyExp, opt => opt.Ignore())
.ForMember(x => x.TermTypeId, opt => opt.MapFrom(x => x.TermTypeId));
I call Map like this:
var newBusiness = Mapper.Map<NewBusinessSubmission, NewBusiness>(newBusinessSubmission);
All the other properties that have similar code in the Set() method map correctly and I can also manually map TermTypeId like this:
newBusinessInstance.TermTypeId = newBusinessSubmissionInstance.TermTypeId;
Any ideas as to why this property is not mapped correctly?
Thanks.