0

I have these model and DTOs

public class ServiceModel
{
    public string ServiceId { get; set; }
    public string ServiceName { get; set; }
    
    public string ServiceTypeId { get; set; }
    public double QuarterlyCharge { get; set; }
    public double AnnualCharge { get; set; }
}

public class ServiceResponseDto
{
    public string ServiceId { get; set; }
    public string ServiceName { get; set; }
    public IEnumerable<TaxDto> Tax { get; set; }
}

public class TaxDto
{
    public string ServiceTypeId { get; set; }
    public double QuarterlyCharge { get; set; }
    public double AnnualCharge { get; set; }
}

I have IEnumerable of ServiceModel resulting into:

ServiceId ServiceName ServiceTypeId AnnualCharge QuarterlyChar
1 Service 1 1 1
1 Service 2 2 2
1 Service 3 3 3

How do I map it into ServiceResponseDto

This is my current solution

IEnumerable<IGrouping<string, ServiceModel>> groupedservice = serviceQueryResult.GroupBy(c => c.ServiceId);
ServiceResponseDto mappedService = _mapper.Map<IEnumerable<IGrouping<string, ServiceModel>>, ServiceResponseDto >(groupedservice );

My mapping:

CreateMap<IEnumerable<IGrouping<string, ServiceModel>>, ServiceResponseDto>()
    .ForMember(dest => dest.ServiceId, opt => opt.MapFrom(src => src.FirstOrDefault().Key))
    .ForMember(dest => dest.ServiceName, opt => opt.MapFrom(src => src.FirstOrDefault().FirstOrDefault().ServiceName))
    .ForMember(dest => dest.Tax , opt => opt.MapFrom(src => src.Select(c => new TaxDto() { ServiceTypeId  = c.FirstOrDefault().ServiceTypeId , QuarterlyCharge = c.FirstOrDefault().QuarterlyCharge, AnnualCharge  = c.FirstOrDefault().AnnualCharge } )));

Expected Result:

new ServiceResponseDto()
{
    ServiceId  = "1",
    ServiceName = "Service"
    Tax = new IEnumerable<TaxDto>()
    {
        new = TaxDto(){ServiceTypeId=ServiceType1, QuarterlyCharge =1, AnnualCharge=1},
        new = TaxDto(){ServiceTypeId=ServiceType2, QuarterlyCharge =2, AnnualCharge=2},
        new = TaxDto(){ServiceTypeId=ServiceType3, QuarterlyCharge =3, AnnualCharge=3},
    }
}

Actual Result: Only 1 record shows up after mapping

new ServiceResponseDto()
{
    ServiceId  = "1",
    ServiceName = "Service"
    Tax = new IEnumerable<TaxDto>()
    {
        new = TaxDto(){ServiceTypeId=ServiceType1, QuarterlyCharge =1, AnnualCharge=1}
    }
}
  • Unrelated: https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency – Fildor Mar 18 '21 at 15:56
  • 1
    I'll take this into cosideration @Fildor – Byron Scott Mar 18 '21 at 16:06
  • You create a map from `IEnumerable>` to a single `ServiceResponseDto`. I think you want to define a map for `IGrouping` to `ServiceResponseDto` (Automapper will then take care of the rest) –  Mar 18 '21 at 16:10

1 Answers1

1

So basically you created a mapping from an IEnumerable<IGrouping<string, ServiceModel>> to a single ServiceModel. But you seem to instead want to create a map for IGrouping<string, ServiceModel> to a ServiceModel.

So change your mapping to:

CreateMap<IGrouping<string, ServiceModel>, ServiceResponseDto>()
  .ForMember(dest => dest.ServiceId, opt => opt.MapFrom(src => src.Key))
  .ForMember(dest => dest.ServiceName, opt => opt.MapFrom(src => src.FirstOrDefault().ServiceName))
  .ForMember(dest => dest.Tax, opt => opt.MapFrom(src => src.Select(c => new TaxDto() { ServiceTypeId = c.ServiceTypeId, QuarterlyCharge = c.QuarterlyCharge, AnnualCharge = c.AnnualCharge })));

And then in code call:

var mappedServices = mapper.Map<IEnumerable<IGrouping<string, ServiceModel>>, IEnumerable<ServiceResponseDto>>(groupedServices);

Keep in mind though that since you started with a IEnumerable<IGrouping<string, ServiceModel>> you'll end up with an IEnumerable<ServiceResponseDto>

See it in action here: https://dotnetfiddle.net/YzIlDt

Hope this helps and good luck on your project!