C# Automapper on the nested list - c#-4.0

I've the following dtos and I'm trying to use automapper, but couldn't quite understand on how to do the same, as this is the first time I'm using automapper any help is really appreciated
string order {get;set;}
string orderType {get;set;}
List<OrderItem> Items {get;set;}
}
public class OrderItem{
string itemID {get;set;}
Price price {get;set;}
}
public class Price {
string total {get;set;}
string regular {get;set;}
}
public class request {
string order {get;set;}
string orderType {get;set;}
List<Item> Items {get;set;}
}
public class Item {
string itemID {get;set;}
string itemPrice {get;set;}
string regularPrice {get;set;}
}
I'm trying the following
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<request,requestDTO>()
.ForMember(dest => dest.order, act=>act.MapFrom(src => src.order))
.ForMember(dest => dest.orderType, act=>act.MapFrom(src => src.orderType))
})
How do I create mapping to map
**
src.item.itemID to dest.item.itemID
src.item.itemPrice to dest.item.price.total
src.item.regularPrice to dest.item.price.regular**
for all the items in my source array

Just create another map for Item and OrderItem as follows:
cfg.CreateMap<Item, OrderItem>()
.ForPath(dest => dest.price.total, act => act.MapFrom(src => src.itemPrice))
.ForPath(dest => dest.price.regular, act =>act.MapFrom(src => src.item.regularPrice));
Also note that the mapper <request,requestDTO> does not need any explicit ForMember call, as both objects have identical property names:
cfg.CreateMap<request,requestDTO>();

Related

How to conditionally map from two sources to a destination in AutoMapper

I have a PITA legacy DB model. Here is the relevant portion
class SalesOrder
{
public Recipient OrderBy {get;set;}
public Recipient BillTo {get;set;}
public List<SalesOrderLine> Lines {get;set;}
}
class SalesOrderLine
{
public Recipient ShipTo {get;set;}
public Address ShipToAddress {get;set;}
}
class Recipient
{
public Address DefaultAddress {get;set;}
}
Now comes the fun part.
class RecipientDTO {
public string Name {get;set;}
public string Address1 {get;set;}
public string Address2 {get;set;}
...
}
I have the OrderDTO that needs to be like this
new OrderDTO {
OrderBy = new RecipientDTO {
Name = OrderBy.Name,
Address1 = OrderBy.DefaultAddress.Addr1,
....
}
BillTo = new RecipientDTO {
Name = BillTo.Name,
Address1 = BilLTo.DefaultAddress.Addr1,
....
}
Lines = Lines.Select (l => new SalesOrderLineDTO {
ShipTo = new RecipientDTO {
Name = ShipTo.Name,
Address1 = l.ShipToAddress.Addr1, //NOTE. THIS IS NOT USING DEFAULT ADDRESS
....
}
} )
}
How do I write the mapping configuration in Auto Mapper for this to make sure the projection emits the chosen columns. If I use CustomResolver, the projection is not emitting the sql and it goes to the DB every time i access the address. Mucho sad!
To anyone who is interested , i have a backreference to Recipient from Address. SO I was able to do this following
m.CreateMap<SalesOrder, OrderDTO>()
.ForMember(d => d.OrderBy, conf => conf.MapFrom(o => o.OrderBy.DefaultAddress))
.ForMember(d => d.BillTo, conf => conf.MapFrom(o => o.BillTo.DefaultAddress));
m.CreateMap<Address, RecipientDTO>()
.ForMember(r => r.CustomerRecipientId, conf => conf.MapFrom(ra => ra.Recipient.CustRecipId))
.ForMember(r => r.Address1, conf => conf.MapFrom(ra => ra.Addr1))
.ForMember(r => r.Address2, conf => conf.MapFrom(ra => ra.Addr2))
....
m.CreateMap<SalesOrderLine, OrderLineDTO>()
.ForMember(l => l.OrderQuantity, conf => conf.MapFrom(l => l.OrderQty ?? 0))
.ForMember(l => l.ShipTo, conf => conf.MapFrom(z => z.ShipToAddress));

How to map an object to a another object with some properties in a child object

Can any one suggest to me where i made the mistake?
public class DataModelProduct
{
public int Id {get;set;}
public string Name {get;set;}
public string Price {get;set;};
public string Brand {get;set;}
public string Color {get;set;}
public string Dimentions {get;set;}
public string Type {get;set;}
public string Network {get;set;}
}
public class Product
{
public int Id {get;set;}
public string Name {get;set;}
public string Price {get;set;}
public Specification Spec {get;set;}
}
public class Specification
{
public string Brand {get;set;}
public string Color {get;set;}
public string Dimentions {get;set;}
public string Type {get;set;}
public string Network {get;set;}
}
AutoMapper.Mapper.CreateMap< DataModelProduct, Product>();
AutoMapper.Mapper.CreateMap< DataModelProduct, Specification>();
You can assume Product class is Core Model and DataModelProduct is a Database Model
The Product properties are mapped but the Specification property is null.
You need to give all your properties accessors for AutoMapper to function:
e.g.
public string Brand { get; set; }
public Specification Spec { get; set; }
And your mapping init code should be something like
var config = new MapperConfiguration(cfg => {
cfg.CreateMap< DataModelProduct, Product>();
cfg.CreateMap< DataModelProduct, Specification>();
});
And your runtime code like:
var product = Mapper.Map(dataModelProduct, new Product());
And the mapping to Specification:
var product = Mapper.Map(dataModelProduct, new Product());
product.Specification = new Specification();
Mapper.Map(dataModelProduct, product.Specification);

Automapper mapping element with subelement that is list to the same Destination

I have the following structure (simplified):
class Source {
string test {get; set;}
List<SubClass> items {get; set;}
}
class SubClass {
string rating {get; set;}
string otherrating {get; set;}
}
class Destination {
string test {get; set;}
sttring rating {get; set;}
string otherrating {get; set;}
}
I need to use Automapper like this:
Source -> Destination (this will affect "test" property)
Source.Items[0] -> `Desination` (this will affect "rating" && "otherrating" property)
I would like to do this using automapper, because I have more fields than in above example
Can you give me suggestions? I am able to create map just for Source (without SubClass).
Mapper.CreateMap<Source, Destination>().ReverseMap();
...
var src = GetSourceWithListsFromDB(); // returns object of class Source
...
var model = Mapper.Map<Source, Destination>(src); // this maps Source, but doesn't map Source.Items[0].rating
I have tried the following mapping:
Mapper.CreateMap<Source, Destination>().ForMember(dest => dest, opt=>opt.MapFrom(src => src.items[0]))
but this throws error.
You need to specify the mapping for both rating and otherrating fields
Mapper.CreateMap<Source, Destination>()
.ForMember(dest => dest.rating, opt => opt.MapFrom(s => s.items[0].rating))
.ForMember(dest => dest.otherrating, opt => opt.MapFrom(s => s.items[0].otherrating));
Mapper.CreateMap<Destination, Source>()
.ForMember(dest =>dest.items, opt => opt.MapFrom(s=> new List<SubClass> {new SubClass(){ rating = s.rating, otherrating = s.otherrating}}));

Automapper map nested collection

I'm new to Automapper, and struggling to get a custom mapping working. I'm using 1.1 so that it works with .net 3.5.
Essentially, I want to create a list for my DTO which is built using one subclass contained within the list class of the parent model.
Below should better illustrate what I mean:
public class RedCar
{
public string Name{get;set;}
public List<RedCarPart> RedCarParts(get;set;}
}
public class RedCarPart
{
public string RedCarSerial{get;set;}
public CarPart Carpart {get;set;}
}
public class CarPart
{
public int PartID {get;set;}
public string Description {get;set;}
}
public class CarDTO
{
public string name{get;set;}
public List<CarPartDTO> carparts{get;set;}
}
public class CarPartDTO
{
public int PartID {get;set;}
public string description {get;set;}
}
I don't need the extra information provided within RedCarPart, and so I just need a list of CarParts.
I know I can just replicate RedCarPartDTO, and ignore the fields I don't need, but rather than pass that down to the client, I feel it would be better to see if I can just map a list of CarParts.
I'm thinking it must be to do with map from, but I'm having trouble with how I'm doing this:
Mapper.CreateMap<RedCar, CarDTO>()
.ForMember(s => s.CarParts, c => c.MapFrom(m => m.RedCarParts));
Mapper.CreateMap<RedCarPart, CarPartDTO>()
.ForMember(s => s.PartID, c => c.MapFrom(m => m.CarPart.PartID))
.ForMember(s => s.Description, c => c.MapFrom(m => m.CarPart.Description));

AutoMapper Custom Collections

I am getting an AutoMapper Exception when i try to Map my DomainModel to ViewModel,
Here is my Domain Model Class,
public class Source{
public string Name {get;set;}
..............
public CustomCollection EmpDetails {get;set;}
}
public class CustomCollection:CollectionBase,IEnumerable<ClassA> {
public CustomCollection{}
public int Add(ClassA classA)
{
return List.Add(classA);
}
..........
}
public class ClassA{
public string EmpNumber {get;set;}
public string EmpName {get;set;}
public string Designation {get;set;}
}
Here is my ViewModel
public class SourceDTO{
public string Name {get;set;}
public IList<EmpDTO> EmpDetails {get;set;}
}
public class EmpDTO{
public string EmpNumber {get;set;}
public string EmpName {get;set;}
public string Designation {get;set;}
}
Here is my AutoMapper Code,
AutoMapper.Mapper.CreateMap<Source, SourceDTO>()
.ForMember(x => x.EmpDetails, y => y.MapFrom(src => src.EmpDetails));
I am getting error here, It doesn't say any detail inner exceptions,
I hope someone can help us out.
You need to include a mapping to go from ClassA to EmpDTO:
Mapper.CreateMap<ClassA, EmpDTO>();
And you should be all set.

Resources