0

I am working on a ASP.NET MVC web app. I recently upgraded my AutoMapper references to 4.2.1 and am having all sorts of fits with it. It has now brought down my production application.

I fixed all errors returned as a result of Mapper.AssertConfigurationIsValid(); so now no errors are produced. However, at turn time, when I call Mapper.Map<ConsumeInventoryViewModel>(pullListDetailViewModel); I get the error:

[AutoMapperMappingException: Missing type map configuration or unsupported mapping.

Mapping types:
PullListDetailViewModel -> ConsumeInventoryViewModel
OTIS.AppServ.InventoryMgmt.ViewModels.PullListDetailViewModel -> OTIS.AppServ.InventoryMgmt.ViewModels.ConsumeInventoryViewModel

Destination path:
ConsumeInventoryViewModel

Source value:
OTIS.AppServ.InventoryMgmt.ViewModels.PullListDetailViewModel]

Of importance is that I get this error for ALL mappings that I have and call, not just one...well I should say for multiple...I haven't tried all, but for the ones I have called, it creates the error.

Here are some of the particulars:

The Models:

public class AutoPullViewModel
{
    public bool autoLocateOnPull { get; set; }
}

public class PullListDetailViewModel : AutoPullViewModel
{
    public int? AllocatedInventoryId { get; set; }

    [Display(Name = "Work Release")]
    public int WorkReleaseHeaderId { get; set; }
    public OrderHeader.OrderTypes OrderTypeEnum { get; set; }

    [Display(Name = "Order/Job")]
    public int? OrderId { get; set; }

    [Display(Name = "Part Nbr")]
    public int? OrderDetailId { get; set; }

    [Display(Name = "Work Order")]
    public int? WorkOrderId { get; set; }
    public int? WorkOrderDetailId { get; set; }
    public bool IsInventoriedItem { get; set; }

    [Display(Name = "Container")]
    public int? InventoryContainerHeaderId { get; set; }
    public string OriginalContainerLocationBarcode { get; set; }

    public int? LocationInventoryId {get; set;}
    public string RequiredLocationBarcode { get; set; }

    [Display(Name = "Location")]
    public string LocationDescription { get; set; }

    public int ItemId { get; set; }
    public string SKU { get; set; }
    public string RequiredItemBarcode { get; set; }

    [Display(Name = "Item/Material")]
    public string ItemDescription { get; set; }
    public string ItemImageURL { get; set; }

    [Display(Name = "Qty")]
    [DisplayFormat(DataFormatString = "{0:N1}")]
    public decimal RequiredQuantity { get; set; }
    public string QuantityDescription { get; set; }
    public string QuantityUOM { get; set; }
}

//Direct user to location for selected material
public class ConsumeInventoryViewModel : PullListDetailViewModel
{
    [Display(Name = "Scan Location")]
    public string ScannedLocationBarcode { get; set; }

    [Display(Name = "Scan Item")]
    public string ScannedItemBarcode { get; set; }

    [Display(Name = "Scan Container")]
    public int? ScannedContainerId { get; set; }

    [Required]
    [Display(Name = "Act Qty")]
    [UIHint("TextBoxFor_75w")]
    public decimal? ConfirmedQty { get; set; }

    [Display(Name = "Only Remnants?")]
    public bool Remnant { get; set; }

}

Config Call in Global.asax Application_Start

protected void Application_Start()
{
  ...
    AutoMapperConfiguration.Configure();
}

The static configurator:

public static class AutoMapperConfiguration
{
    public static void Configure()
    {
        //see https://github.com/AutoMapper/AutoMapper/wiki/Configuration
        Mapper.Initialize(cfg =>
        {                
            cfg.CreateMap<PullListDetailViewModel, ConsumeInventoryViewModel>()
                .ForMember(dest => dest.ScannedLocationBarcode, option => option.Ignore())
                .ForMember(dest => dest.ScannedItemBarcode, option => option.Ignore())
                .ForMember(dest => dest.ScannedContainerId, option => option.Ignore())
                .ForMember(dest => dest.ConfirmedQty, option => option.Ignore())
                .ForMember(dest => dest.Remnant, option => option.Ignore())
                ;                                 
        });

        Mapper.AssertConfigurationIsValid();
    }    
}

And finally the runtime call to the map:

var consumeInventoryViewModel = Mapper.Map<ConsumeInventoryViewModel>(pullListDetailViewModel);

Like this other post, after I restart the website in IIS (and I can debug and ensure that the Config and Validation are being hit, the first call to the runtime map works, but all subsequent ones fail.

Anyone have any pointers/ideas?

halfer
  • 19,824
  • 17
  • 99
  • 186
crichavin
  • 4,672
  • 10
  • 50
  • 95
  • 2
    That seems odd. A bit of a stretch, admittedly, but have you checked that there's no other AutoMapper Initialization code lurking about? – stuartd Jul 22 '16 at 23:21
  • Not a stretch at all actually, good call. There may be one in a class library project we just added to the solution. So if there is, it overwrites the config I'm the main aspinwall.net project I presume? – crichavin Jul 23 '16 at 00:02
  • Yup, Initialization overwrites existing mappings, it's not additive. – stuartd Jul 23 '16 at 00:07
  • @stuartd so that was the problem. We had another set of Initialization code being called in our Hangfire scheduler project, which is also initialized on the Web app startup. Now I have questions on how to initialize those AutoMapper configs...but I'll post that in another question. If you make your comment in the form of an answer, I will accept it. Thanks again @stuartd! – crichavin Jul 24 '16 at 16:29

0 Answers0