Kamran Pervaiz
Kamran Pervaiz

Reputation: 1931

Automapper better way of mapping property with custom logic

I have a simple class called Supplier which has contacts and contact can have addresses. right now we are using only 1 contact and 1 address (line1 to line4) in that contact. In future we might use multiple contacts having multiple addresses. below is my class

public class SupplierDto
    {

        public string Name { get; set; }
        public string Alias { get; set; }
        public int? SupplierTypeId { get; set; }
        public int? WebclicsManufacturerId { get; set; }
        public string SAPCode { get; set; }

        public string Line1 { get; set; }
        public string Line2 { get; set; }

        public string Line3 { get; set; }
        public string Line4 { get; set; }
        public int CountryId { get; set; }
        public string PostalCode { get; set; }


        public string ContactName { get; set; }
        public string ContactEmail { get; set; }
        public string ContactTelephone { get; set; }
        public string ContactJobTitle { get; set; }
    }

My Supplier class is a bit complex, so I am trying to map from Supplier to DTO and below is my mapping.

CreateMap<Supplier, SupplierDto>()
                .ForMember(dest => dest.Line1, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line1))
                .ForMember(dest => dest.Line2, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line2))
                .ForMember(dest => dest.Line3, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line3))
                .ForMember(dest => dest.Line4, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.Line4))
                .ForMember(dest => dest.CountryId, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.CountryId))
                .ForMember(dest => dest.PostalCode, options => options.MapFrom(source => source.SupplierContacts.First().Contact.EntityAddresses.First().Address.PostalCode))
                .ForMember(dest => dest.ContactName, options => options.MapFrom(source => source.SupplierContacts.First().Contact.Name))
                .ForMember(dest => dest.ContactEmail, options => options.MapFrom(source => source.SupplierContacts.First().Contact.Email))
                .ForMember(dest => dest.ContactTelephone, options => options.MapFrom(source => source.SupplierContacts.First().Contact.Telephone))
                .ForMember(dest => dest.ContactJobTitle, options => options.MapFrom(source => source.SupplierContacts.First().Contact.JobTitle));

As you can see I have custom logic for each column. Now problem is if there is no contact/address, code breaks because I am using

First()

from LINQ, is there a better way to check if contacts exists then do mapping and if it has addresses then proceed with address mapping?

Upvotes: 0

Views: 532

Answers (1)

Rabban
Rabban

Reputation: 2581

Just create an ContactDto and add it to the SupplierDto, then move all contact relevant properties to the ContactDto.

public class ContactDto
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }

    public string Line3 { get; set; }
    public string Line4 { get; set; }
    public int CountryId { get; set; }
    public string PostalCode { get; set; }

    public string ContactName { get; set; }
    public string ContactEmail { get; set; }
    public string ContactTelephone { get; set; }
    public string ContactJobTitle { get; set; }
}

public class SupplierDto
{
    public string Name { get; set; }
    public string Alias { get; set; }
    public int? SupplierTypeId { get; set; }
    public int? WebclicsManufacturerId { get; set; }
    public string SAPCode { get; set; }

    public ContactDto Contact { get; set; }
}

Then the mapping should look something like this

CreateMap<Supplier, SupplierDto>()
    .ForMember(dest => dest.Contact, options => options.MapFrom(source => source.SupplierContacts.FirstOrDefault()));

If Contact is null then AutoMapper didn't try to map it. If you want in the Future support multiple Contacts on the Supplier, then just change the ContactDto Contact Property to a List<ContactDto> and remove the .FirstOrDefault() in the Mapping.

Upvotes: 1

Related Questions