AutoMapper 异常:缺少类型映射配置或不支持的映射
AutoMapper Exception : Missing type map configuration or unsupported mapping
我在 ASP.NET WEB API 中使用 Ninject 和 AutoMapper 将服务模型映射到实体模型。在此,我试图首先将 'NewUser' 服务模型映射到 'User' 实体模型并将 'NewUser' 排序到数据库,最后将新存储的数据映射到 'User' 服务模型。
这是 NinjectDependencyResolver class:
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);
}
}
以下是 NewUser
到 User
实体和 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
class,我在这里将所有映射配置为单个 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;
}
问题是每当我通过 fiddler 调用 Api 的 Post
方法时,它都会抛出以下异常:
{"Message":"An error has occurred.","ExceptionMessage":"Missing type
map configuration or unsupported mapping.\r\n\r\nMapping
types:\r\nNewUser -> User\r\nTestApp.Web.Api.Models.NewUser ->
TestApp.Data.Entities.User","ExceptionType":"AutoMapper.AutoMapperMappingException"}
请帮我找出原因。
更新:
我尝试在 mathod 本身上添加初始化映射并且它起作用了。看起来映射正在 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;
}
您只能运行 初始化方法一次。所以我建议你做的是改变代码如下:
更改 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 中将方法更改为 运行 仅初始化一次
public void Configure(IEnumerable<IAutoMapperTypeConfigurator> autoMapperTypeConfigurations)
{
Mapper.Initialize(config => autoMapperTypeConfigurations.ToList().ForEach(m => m.Configure(config)));
Mapper.AssertConfigurationIsValid();
}
这应该有效。
我在 ASP.NET WEB API 中使用 Ninject 和 AutoMapper 将服务模型映射到实体模型。在此,我试图首先将 'NewUser' 服务模型映射到 'User' 实体模型并将 'NewUser' 排序到数据库,最后将新存储的数据映射到 'User' 服务模型。 这是 NinjectDependencyResolver class:
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);
}
}
以下是 NewUser
到 User
实体和 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
class,我在这里将所有映射配置为单个 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;
}
问题是每当我通过 fiddler 调用 Api 的 Post
方法时,它都会抛出以下异常:
{"Message":"An error has occurred.","ExceptionMessage":"Missing type map configuration or unsupported mapping.\r\n\r\nMapping types:\r\nNewUser -> User\r\nTestApp.Web.Api.Models.NewUser -> TestApp.Data.Entities.User","ExceptionType":"AutoMapper.AutoMapperMappingException"}
请帮我找出原因。
更新:
我尝试在 mathod 本身上添加初始化映射并且它起作用了。看起来映射正在 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;
}
您只能运行 初始化方法一次。所以我建议你做的是改变代码如下:
更改 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 中将方法更改为 运行 仅初始化一次
public void Configure(IEnumerable<IAutoMapperTypeConfigurator> autoMapperTypeConfigurations)
{
Mapper.Initialize(config => autoMapperTypeConfigurations.ToList().ForEach(m => m.Configure(config)));
Mapper.AssertConfigurationIsValid();
}
这应该有效。