Automapper exception: “Missing type map configurat

2019-02-21 22:50发布

问题:

I am trying to use Ninject in an ASP.NET MVC 5 application that uses AutoMapper for mapping the Model to the View Model and vice versa. Unfortunately I get an error message that states that the type map configuration is missing.

I created a Ninject dependency resolver:

namespace MyNamespace.Infrastructure
{
    public class NinjectDependencyResolver: IDependencyResolver
    {
        private IKernel kernel;

        public NinjectDependencyResolver(IKernel kernelParam)
        {
            kernel = kernelParam;
            AddBindings();
        }

        public object GetService(Type serviceType)
        {
            return kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return kernel.GetAll(serviceType);
        }

        private void AddBindings()
        {
            kernel.Bind<IMyBLL>().To<MyBLL>();
        }
    }
}

I use this to create a controller:

namespace MyNamespace.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        private IMyBLL _myBLL;

        public HomeController(IMyBLL myBLLParam)
        {
            _myBLL = myBLLParam;
        }

        public PartialViewResult AddRecord()
        {
            return PartialView(new AddRecordViewModel());
        }

        [HttpPost]
        public void AddRecord(AddRecordViewModel recordViewModel)
        {
            var record = Mapper.Map<Record>(recordViewModel);

            _myBLL.AddRecord(record, User.Identity.Name);
        }
    }
}

Global.asax:

namespace MyNamespace.WebApplication
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            ApplicationUserManager.StartupAsync();
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AutoMapperWebConfiguration.Configure();
        }
    }
}

This calls the AutoMapper configuration:

namespace MyNamespace.WebApplication.Infrastructure
{
    public static class AutoMapperWebConfiguration
    {
        public static void Configure()
        {
            Mapper.Initialize(cfg => cfg.AddProfile(new RecordProfile()));
        }
    }

    public class RecordProfile : Profile
    {
        protected override void Configure()
        {
            Mapper.CreateMap<AddRecordViewModel, Record>().ReverseMap();
        }
    }
}

When I run this I get the following error message:

Missing type map configuration or unsupported mapping.

Mapping types:
AddRecordViewModel -> Record
 MyNamespace.WebApplication.ViewModels.Home.AddRecordViewModel -> MyNamespace.Model.Record

 Destination path:
 Record

 Source value:
 MyNamespace.WebApplication.ViewModels.Home.AddRecordViewModel

Do I miss something. It worked fine before I used the Ninject dependency resolver. Now it does not seem to find the mappings.


Edit:

If I add the Mapping Creation directly to the controller method it works:

[HttpPost]
public void AddRecord(AddRecordViewModel recordViewModel)
{
    Mapper.CreateMap<AddRecordViewModel, Record>().ReverseMap();
    var record = Mapper.Map<Record>(recordViewModel);

    _myBLL.AddRecord(record, User.Identity.Name);
}

The mapping itself and the models and view models do not seem to be the problem. I guess that the programm somehow does not find the mappings.

Even if I call the Auto Mapper Web Configuration in the controller method it works:

public void AddRecord(AddRecordViewModel recordViewModel)
{
    Infrastructure.AutoMapperWebConfiguration.Configure();

    var record = Mapper.Map<Record>(recordViewModel);

    _myBLL.AddRecord(record, User.Identity.Name);
}

回答1:

You need to add the reverse mapping also. You can do it one of two ways:

Mapper.CreateMap<AddRecordViewModel, Record>();
Mapper.CreateMap<Record, AddRecordViewModel>();

or in one go like so:

Mapper.CreateMap<AddRecordViewModel, Record>().ReverseMap();

The latter is preferable if you ask me.



回答2:

Don't call Mapper.CreateMap in your profile. Call base.CreateMap, and you're set:

public class RecordProfile : Profile
{
    protected override void Configure()
    {
        base.CreateMap<AddRecordViewModel, Record>().ReverseMap();
    }
}


回答3:

Mapper.Initialize() should be used strictly once per solution.

If you call Initialize() somewhere later it will override all your previous mappings. Inspect your code attentively, guess, you'll find a call of this method in another place.

P.S.: That wasn't initial behavior of Automapper early, as I could see in pieces of code created 3 and more years ago on GitHub.



回答4:

I had a similar problem, I forgot to register in the Global.asax

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {


        AutoMapperConfig.RegisterMappings();

    }
}


回答5:

In my case the problem was that some default Automapper mappings were registered with the IoC.

builder.Register(_ => AutomapperConfiguration.Configure()).As<IMapper>().SingleInstance();

The mapping that were failing were registered in a different place, the service configuration

static void Main(string[] args)
{
    var container = ConfigureDependencies();
    AutoMapping.Configure();

The project were was getting this error was a test project where the service configuration was not executed. When debugged had the illusion that the failing mappings were registered, as could see the ones from IoC mappings.

Solution, make sure all the mappings were registered in the test solution.