【问题标题】:AutoMapper Exception : Missing type map configuration or unsupported mappingAutoMapper 异常:缺少类型映射配置或不支持的映射
【发布时间】:2016-08-26 10:16:43
【问题描述】:

我在带有 AutoMapper 的 ASP.NET WEB API 中使用 Ninject 将服务模型映射到实体模型。在此,我尝试首先将“NewUser”服务模型映射到“User”实体模型,并将“NewUser”排序到数据库,最后将新存储的数据映射到“User”服务模型。 这是 NinjectDependencyResolver 类:

public sealed class NinjectDipendencyResolver :IDependencyResolver 
    {
        private readonly IKernel _container;

        public NinjectDipendencyResolver(IKernel contanier)
        {
            _container = contanier;
        }

        public IKernel Container
        {
            get { return _container; }
        }
        public object GetService(Type servicetType)
        {
            return _container.TryGet(servicetType);
        }
        public  IEnumerable<object> GetServices(Type ServiceType)
        {
            return _container.GetAll(ServiceType);
        }
        public IDependencyScope BeginScope()
        {
            return this;
        } 
        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }

这里是NewUserUser 实体和User 实体到User 服务模型映射实现:

Mapper.Initialize(cfg => cfg.CreateMap<Models.NewUser, Data.Entities.User>()
        .ForMember(m => m.UserId, i => i.Ignore())
                .ForMember(m => m.AuthKey, i => i.Ignore())
                .ForMember(m => m.DisabledDate, i => i.Ignore())
                .ForMember(m => m.JoinedDate, i => i.Ignore())
                .ForMember(m => m.LastSeen, i => i.Ignore())
                .ForMember(m => m.Version, i => i.Ignore())
                .ForMember(m => m.Goals, i => i.Ignore()));
Mapper.Initialize(cfg => cfg.CreateMap<Data.Entities.User, Models.User>()
            .ForMember(m => m.Links, i => i.Ignore())
            .ForMember(m => m.Goals, i => i.MapFrom(j => Mapper.Map<ICollection<Data.Entities.Goal>, List<Models.Goal>>(j.Goals)))
            .ReverseMap()
            .ForMember(m => m.Goals, i => i.MapFrom(j => Mapper.Map<List<Models.Goal>, ICollection<Data.Entities.Goal>>(j.Goals)))
            .ForMember(m => m.Version, i => i.Ignore()));

这是NinjectConfigurator 类,我将所有映射配置为单个IAutoMapperTypeConfigurator

    public class NinjectConfigurator
        {
            public void Configure(IKernel container)
            {
                AddBindings(container);
            }
            private void AddBindings(IKernel container)
            {
                ConfigureUnitOfWork(container);
                ConfigureAutoMapper(container);
            }
            private void ConfigureUnitOfWork(IKernel container)
            {
                var unitOfWork = new UnitOfWork(new AppTestDBContext());
                container.Bind<IUnitOfWork>().ToConstant(unitOfWork);
            }
            private void ConfigureAutoMapper(IKernel container)
            {
                container.Bind<IAutoMapper>()
                            .To<AutoMapperAdapter>()
                            .InSingletonScope();
                container.Bind<IAutoMapperTypeConfigurator>()
                            .To<NewUserMapper>()
                            .InSingletonScope();
                container.Bind<IAutoMapperTypeConfigurator>()
                            .To<UserMapper>()
                            .InSingletonScope();
            }
}

还有AutoMapperConfigurator 我在其中一次性配置映射:

public class AutoMapperConfigurator
    {
        public void Configure(IEnumerable<IAutoMapperTypeConfigurator> autoMapperTypeConfigurations)
        {
            autoMapperTypeConfigurations.ToList().ForEach(m => m.Configure());
            Mapper.AssertConfigurationIsValid();
        }
    }

这里是我的 Global.ascx.cs,我在 Application_Start 上配置映射:

protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            new AutoMapperConfigurator().Configure(
                WebContainerManager.GetAll<IAutoMapperTypeConfigurator>());
        }

控制器动作:

public async Task<IHttpActionResult> Post(NewUser newUser)
        {
            var createdUser = _iUserMaintenanceProcessor.Add(newUser);
            if (createdUser != null)
            {
                return Ok(createdUser);
            }
            else
                return NotFound();
        }

public Models.User Add(NewUser newUser)
        {
            var userEntity = _autoMapper.Map<Data.Entities.User>(newUser);
            _unitOfWork.User.Add(userEntity);
            var user = _autoMapper.Map<Models.User>(userEntity);
            return user;
        }

问题是每当我通过提琴手调用 Api 的 Post 方法时,它都会抛出以下异常:

{"Message":"发生错误。","ExceptionMessage":"缺少类型 映射配置或不支持的映射。\r\n\r\n映射 类型:\r\nNewUser -> 用户\r\nTestApp.Web.Api.Models.NewUser -> TestApp.Data.Entities.User","ExceptionType":"AutoMapper.AutoMapperMappingException"}

请帮我找出原因。

更新: 我尝试在方法本身上添加初始化映射并且它起作用了。看起来映射正在Application_Start 上初始化,但如上所述,我已经初始化了映射。这是正在工作的更新方法:

public Models.User Add(NewUser newUser)
        {
            Mapper.Initialize(cfg => cfg.CreateMap<Models.NewUser, Data.Entities.User>()
            .ForMember(m => m.UserId, i => i.Ignore())
                    .ForMember(m => m.AuthKey, i => i.Ignore())
                    .ForMember(m => m.DisabledDate, i => i.Ignore())
                    .ForMember(m => m.JoinedDate, i => i.Ignore())
                    .ForMember(m => m.LastSeen, i => i.Ignore())
                    .ForMember(m => m.Version, i => i.Ignore())
                    .ForMember(m => m.Goals, i => i.Ignore()));
            var userEntity = _autoMapper.Map<Data.Entities.User>(newUser);
            _unitOfWork.User.Add(userEntity);
            Mapper.Initialize(cfg => cfg.CreateMap<Data.Entities.User, Models.User>()
            .ForMember(m => m.Links, i => i.Ignore())
            .ForMember(m => m.Goals, i => i.MapFrom(j => Mapper.Map<ICollection<Data.Entities.Goal>, List<Models.Goal>>(j.Goals)))
            .ReverseMap()
            .ForMember(m => m.Goals, i => i.MapFrom(j => Mapper.Map<List<Models.Goal>, ICollection<Data.Entities.Goal>>(j.Goals)))
            .ForMember(m => m.Version, i => i.Ignore()));
            var user = _autoMapper.Map<Models.User>(userEntity);
            return user;
        }

【问题讨论】:

    标签: asp.net-web-api2 ninject automapper


    【解决方案1】:

    您只能运行一次 Initialize 方法。所以我建议你做的是改变代码如下:

    更改 IAutoMapperTypeConfigurator 接口以获取配置属性

    public interface IAutoMapperTypeConfigurator
    {
        void Configure(IMapperConfigurationExpression configuration);
    }
    

    更改映射器以使用此配置属性

    public void Configure(IMapperConfigurationExpression configuration)
    {
        configuration.CreateMap<Models.NewUser, Data.Entities.User>()
        .ForMember(m => m.UserId, i => i.Ignore())
                .ForMember(m => m.AuthKey, i => i.Ignore())
                .ForMember(m => m.DisabledDate, i => i.Ignore())
                .ForMember(m => m.JoinedDate, i => i.Ignore())
                .ForMember(m => m.LastSeen, i => i.Ignore())
                .ForMember(m => m.Version, i => i.Ignore())
                .ForMember(m => m.Goals, i => i.Ignore());
    }
    

    在 AutoMapperConfiguration 中更改方法只运行一次 Initialize

    public void Configure(IEnumerable<IAutoMapperTypeConfigurator> autoMapperTypeConfigurations)
    {
        Mapper.Initialize(config => autoMapperTypeConfigurations.ToList().ForEach(m => m.Configure(config)));
        Mapper.AssertConfigurationIsValid();
    }
    

    这应该可行。

    【讨论】:

    • 感谢您提供有用的信息。有用。我误解了 Initialize 是用来初始化每个映射类型的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 2019-03-01
    • 2017-04-16
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多