I am using Ninject in ASP.NET WEB API with AutoMapper to map Service Models to Entity Model. In this, I am trying to first map 'NewUser' service model to 'User' entity model and soring the 'NewUser' to database and finally mapping the newly stored data to 'User' service model. Here is the 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);
}
}
Here are the NewUser to User enity and User entity to User service model mapping implementations:
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()));
Here is NinjectConfigurator class where I am configuring all the Mappings to single 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();
}
}
And AutoMapperConfigurator where I am configuring the mappings in one go:
public class AutoMapperConfigurator
{
public void Configure(IEnumerable<IAutoMapperTypeConfigurator> autoMapperTypeConfigurations)
{
autoMapperTypeConfigurations.ToList().ForEach(m => m.Configure());
Mapper.AssertConfigurationIsValid();
}
}
And here my Global.ascx.cs where I am configuring the Mappings on Application_Start:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
new AutoMapperConfigurator().Configure(
WebContainerManager.GetAll<IAutoMapperTypeConfigurator>());
}
Controller action:
public async Task<IHttpActionResult> Post(NewUser newUser)
{
var createdUser = _iUserMaintenanceProcessor.Add(newUser);
if (createdUser != null)
{
return Ok(createdUser);
}
else
return NotFound();
}
and
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;
}
The problem is whenever I call the Post method of the Api through fiddler it is throwing following exception:
{"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"}
Please help me to figure out the cause.
UPDATE :
I tried to add initialize the mappings on the mathod itself and it worked. Looks like the mappings are getting initialized on Application_Start but as mentioned above i have initialized the mappings. Here is the updated mehthod which is working:
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;
}