I'm on AutoMapper 4.2 and I cant figure out why I'm getting this error
Autofac.Core.Registration.ComponentNotRegisteredException The requested service 'Navigator.ItemManagement.Data.MappingProfiles.ReportPreferenceReportUserIdsResolver' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
I'm getting this error for my one of my value resolvers
public class ReportPreferenceProfile : Profile
{
protected override void Configure()
{
CreateMap<ReportPreference, ReportPreferenceSummaryDto>()
.ForMember(d => d.Id, o => o.MapFrom(s => s.Id))
.ForMember(d => d.Name, o => o.MapFrom(s => s.Name))
.ForMember(d => d.ReportUserIds, o => o.ResolveUsing<ReportPreferenceReportUserIdsResolver>());
}
}
public class ReportPreferenceReportUserIdsResolver : ValueResolver<IList<ReportUser>, IList<Guid>>
{
protected override IList<Guid> ResolveCore(IList<ReportUser> source)
{
return source.Select(r => r.UserId).ToList();
}
}
I've registered this in my Autofac module
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ReportPreferenceReportUserIdsResolver>().As<IValueResolver>();
//register all profile classes in the calling assembly
var profiles =
from t in typeof(Navigator.ItemManagement.Data.MappingProfiles.PlaceMapperProfile).Assembly.GetTypes()
where typeof(Profile).IsAssignableFrom(t)
select (Profile)Activator.CreateInstance(t);
builder.Register(context => new MapperConfiguration(cfg =>
{
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
})).AsSelf().SingleInstance();
builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve))
.As<IMapper>()
.SingleInstance();
}
UPDATE 1
I tried the suggestion from Lucian Bargaoanu and replaced
builder.RegisterType<ReportPreferenceReportUserIdsResolver>().As<IValueResolver>();
with
builder.RegisterType<ReportPreferenceReportUserIdsResolver>().AsSelf();
Now the error I get is
System.ObjectDisposedException
This resolve operation has already ended. When registering components using lambdas, the IComponentContext 'c' parameter to the lambda cannot be stored. Instead, either resolve IComponentContext again from 'c', or resolve a Func<> based factory to create subsequent components from.
Mapping types: ReportPreference -> IList
1 Navigator.ItemManagement.Core.ItemAggregate.ReportPreference -> System.Collections.Generic.IList
1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]Destination path: ReportJobSummaryDto.Reports.Reports.Reports0[0].ReportUserIds0[0]
Source value: Navigator.ItemManagement.Core.ItemAggregate.ReportPreference ---> AutoMapper.AutoMapperMappingException:
Mapping types: ReportPreference -> IList
1 Navigator.ItemManagement.Core.ItemAggregate.ReportPreference -> System.Collections.Generic.IList
1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]Destination path: ReportJobSummaryDto.Reports.Reports.Reports0[0].ReportUserIds0[0]
I arrived at this Q&A after encountering the same problem.
As @PeterRiesz mentioned in comments, since your
IValueResolver
does not require any dependencies, the simplest solution here would be to change the form in which you wire up the value resolver to just take a manual new instance:This wouldn't require any registration with the Autofac container.
However, you may wish to inject services in to it, or just want to register it with Autofac for other reasons and maintainability.
First, ensure that you've registered your
IValueResolver
type with Autofac as @LucianBargaoanu answered:I was defining my AutoMapper registrations the same way as you, and as a result was also getting the same error you show above.
After much research and trial and error to resolve the error myself, I found this StackOverflow Q&A which led me in the right direction.
You are already setting up the service function for AutoMapper to use to resolve dependencies here:
However, as the error states, the context
c
has been disposed by the time this actually gets executed. The way to fix this is to rewrite the lambda registration as follows:An additional means of registering the service resolver exists as well. You can do it in the MapperConfiguration registration instead as follows:
Either of these appears to be equivalent. I think the latter is cleaner personally.
The take away here is that a new context needs to be resolved in the top-level lambda since the instance being passed in will be disposed by the time the lambda is actually executed.