Search code examples
c#.net-coreautomapper

ASP.NET Core AutoMapper configuration error


I am trying to map an entity with a model but it's giving an error how can I check which property is causing the error?

Error: AutoMapper.AutoMapperMappingException: 'Error mapping types.' AutoMapperMappingException: Missing type map configuration or unsupported mapping.
This exception was originally thrown at this call stack:

AutoMapper.Mapper.MapCore<TSource, TDestination>(TSource, TDestination, AutoMapper.ResolutionContext, System.Type, System.Type, AutoMapper.MemberMap)
AutoMapper.Mapper.AutoMapper.IInternalRuntimeMapper.Map<TSource, TDestination>(TSource, TDestination, AutoMapper.ResolutionContext, System.Type, System.Type, AutoMapper.MemberMap)
AutoMapper.ResolutionContext.MapInternal<TSource, TDestination>(TSource, TDestination, AutoMapper.MemberMap)

public class AutoMapperProfile : Profile
{
    public AutoMapperProfile()
    {
        CreateMap<Account, AccountModel>();
        CreateMap<AccountModel, Account>();

        CreateMap<ServicePlan, ServicePlanModel>()
              .ForMember(ServicePlanModel => ServicePlanModel.ServicePlanDetails, opt => opt.MapFrom(src => src.ServicePlanDetails.ToList()))
              .ForMember(dest => dest.Lines, opt => opt.MapFrom(src => src.NLines ?? default))
              .ForMember(dest => dest.StartDate, opt => opt.MapFrom(src => src.DateStart))
              .ForMember(dest => dest.EndDate, opt => opt.MapFrom(src => src.DateEnd))
              .ForMember(dest => dest.MonthlyCharges, opt => opt.MapFrom(src => src.AmountMonthly))
              .ForMember(dest => dest.OneTimeCharges, opt => opt.MapFrom(src => src.AmountOnetime));
    }
}

public async Task<List<ServicePlanModel>> GetServicePlansWithDetails(long accountId)
{
    var plan = mapper.Map<ServicePlan, ServicePlanModel>(servicePlan);
}

public partial class ServicePlan
{
    public ServicePlan()
    {
        ServicePlanDetails = new HashSet<ServicePlanDetail>();
    }

    public long PlanId { get; set; }
    public decimal PhoneId { get; set; }
    public byte? NLines { get; set; }
    public DateTime? DateStart { get; set; }
    public DateTime? DateEnd { get; set; }
    public decimal? AmountMonthly { get; set; }
    public decimal? AmountOnetime { get; set; }
    public string? ContractType { get; set; }
    public string? CallerId { get; set; }
    public bool? Active { get; set; }
    public short? ResellerId { get; set; }
    public int? OnetimeInvoiceNo { get; set; }
    public bool? IsRequest { get; set; }
    public string? RequestType { get; set; }
    public string? NewValue { get; set; }
    public DateTime? RequestDate { get; set; }
    public string? RequestBy { get; set; }
    public bool? IsRejected { get; set; }
    public bool? IsApproved { get; set; }
    public DateTime? ApprovedWhen { get; set; }
    public string? ApprovedBy { get; set; }
    public string? Comments { get; set; }
    public string? AdditionalDetails { get; set; }
    public string? VideoTronId { get; set; }
    public string? Zone { get; set; }
    public string? PrevProvider { get; set; }
    public bool? Charge911Tax { get; set; }
    public string? ContractTerms { get; set; }
    public long? ContractId { get; set; }
    public int AllowedBandwidth { get; set; }
    public DateTime? ServiceStartDate { get; set; }
    public string? AppointmentTime { get; set; }
    public DateTime? AppointmentEmailSentOn { get; set; }
    public string? TrackingNumber { get; set; }
    public bool? HasNumberPort { get; set; }
    public DateTime? EstPortDate { get; set; }
    public DateTime? PortCompletedOn { get; set; }
    public bool? IsExGbchargesLimited { get; set; }
    public decimal? ExGbchagesLimitAmt { get; set; }
    public bool? IsPreVisitSch { get; set; }
    public DateTime? PreVisitSchDate { get; set; }
    public string? PreVisitSchTime { get; set; }
    public bool? MoniterBwUsage { get; set; }
    public int? BwWarnLimit { get; set; }
    public string? DslaccountId { get; set; }
    public string? BellGisId { get; set; }
    public string? DslPassword { get; set; }
    public bool? IsPasswordPassed { get; set; }
    public bool? IsDslUserPassed { get; set; }
    public string? CogecoId { get; set; }
    public int? ServiceProviderId { get; set; }
    public string? RogersId { get; set; }
    public decimal? InternetSpeed { get; set; }
    public bool? ModemRental { get; set; }
    public bool? RouterRental { get; set; }
    public bool? Atarental { get; set; }
    public string? DslaccountDomain { get; set; }

    [NotMapped]
    public virtual ICollection<ServicePlanDetail> ServicePlanDetails { get; set; }
}

public class ServicePlanModel
{
    public ServicePlanModel()
    {
        ServicePlanDiscounts = new List<ServicePlanDiscount>();
        ServicePlanDetails = new List<ServicePlanDetail>();
    }

    [Key]
    public Int64 PlanId { get; set; }
    public Int64? ContractId { get; set; }
    public int ResellerId { get; set; }
    public Int64 PhoneId { get; set; }
    public bool IsPhone { get; set; }
    public Int32? OneTimeInvoiceId { get; set; }
    public UInt16 Lines { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime? EndDate { get; set; }
    public Decimal MonthlyCharges { get; set; }
    public Decimal OneTimeCharges { get; set; }
    public String ContractType { get; set; }
    public String CallerId { get; set; }
    public Boolean IsActive { get; set; }
    public Boolean IsRequest { get; set; }
    public Boolean IsRejected { get; set; }
    public Boolean IsApproved { get; set; }
    public Boolean Charge911Tax { get; set; }
    public DateTime ApprovedOn { get; set; }
    public String ApprovedBy { get; set; }
    public String Comments { get; set; }
    public String ContractTerms { get; set; }
    public String AdditionalDetails { get; set; }
    public String VideoTronId { get; set; }
    public String Zone { get; set; }
    public String PreviousProvider { get; set; }
    public String RequestType { get; set; }
    public String NewValue { get; set; }
    public DateTime? RequestDate { get; set; }
    public String RequestedBy { get; set; }
    //public PhoneNumber PhoneNumber { get; set; }
    public List<ServicePlanDetail> ServicePlanDetails { get; set; }
    public List<ServicePlanDiscount> ServicePlanDiscounts { get; set; }

    public bool IsLandLinePlan
    {
        get
        {
            if (ServicePlanDetails != null)
            {
                return ServicePlanDetails.Any(spd => new String[] { "landline-r", "landline-b", "plan_10103", "plan_10104", "plan_10105" }.Contains(spd.ServiceCode));
            }

            return false;
        }
    }

    public String ServicePlanName
    {
        get
        {
            if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
            {
                var plan = ServicePlanDetails.SingleOrDefault(spd => spd.IsPlan);
                if (plan != null)
                {
                    if (IsPhone)
                    {
                        return String.Format("{0} ({3}) ({1} x {2})", plan.ServiceTitle, plan.UnitPrice.ToString("N2"), plan.Quantity, PhoneId.ToString("###-###-####"));
                    }

                    return String.Format("{0} ({1} x {2})", plan.ServiceTitle, plan.UnitPrice.ToString("N2"), plan.Quantity);
                }
            }
            return String.Empty;
        }
    }

    public String MonthlyChargesDetails
    {
        get
        {
            if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
            {
                var items = ServicePlanDetails.Where(spd => spd.IsPlan == false & spd.UnitPrice > 0 & spd.ServiceType.Equals(Constants.SERVICE_TYPE_MONTHLY)).ToList();

                var details = new StringBuilder();

                foreach (var spd in items)
                {
                    details.Append(String.Format("{0} ({1} x {2}) ", spd.ServiceTitle, spd.UnitPrice.ToString("N2"),
                                                 spd.Quantity));
                }

                return details.ToString();
            }

            return String.Empty;
        }
    }

    //public String OnetimeChargesDetails
    //{
    //    get
    //    {
    //        if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
    //        {
    //            var items = ServicePlanDetails.Where(spd => spd.IsPlan == false & spd.UnitPrice > 0 & spd.ServiceType.Equals(Constants.SERVICE_TYPE_ONETIME)).ToList();

    //            var details = new StringBuilder();
    //            foreach (var spd in items)
    //            {
    //                details.Append(String.Format("{0} ({1} x {2}) ", spd.ServiceTitle, spd.UnitPrice.ToString("N2"),
    //                                             spd.Quantity));
    //            }
    //            return details.ToString();
    //        }
    //        return String.Empty;
    //    }
    //}

    public List<ServicePlanDetail> OnetimeChargesDetails
    {
        get
        {
            if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
            {
                return ServicePlanDetails.Where(spd => spd.IsPlan == false & spd.ServiceType.Equals(Constants.SERVICE_TYPE_ONETIME)).ToList();
            }

            return null;
        }
    }

    public List<ServicePlanDetail> FreeServicesDetails
    {
        get { return ServicePlanDetails != null ? ServicePlanDetails.Where(s => s.UnitPrice == 0 && !s.ServiceType.Equals("month")).ToList() : null; }
    }

    public List<ServicePlanDetail> DiscountedServicesDetail
    {
        get
        {
            return ServicePlanDetails != null ?
            ServicePlanDetails.Where(s => s.ResellerService != null && s.UnitPrice < s.ResellerService.SuggestedPrice && !s.ServiceType.Equals("month")).ToList() : null;
        }
    }

    public string Modem_MAC { get; set; }
    public string TrackingNumber { get; set; }
}

I tried debugging but could not find the error.


Solution

  • Take a look at the source for AutoMapperMappingException. There are a number of properties on the exception that can be examined while under a debugger.

    From the source...

    public TypePair? Types { get; set; }
    public TypeMap TypeMap { get; set; }
    public MemberMap MemberMap { get; set; }
    

    These properties are used to create the string for the Message property.

    If for some reason that doesn't give you enough information, a way more intensive and semi-destructive way (have a backup of your source) is to cut half of the properties from the source/target types and see if the error still occurs. If yes, cut in half again, if no take the other properties and try again.

    Basically, you are doing a binary search to narrow down the problem until it becomes obvious.