Automapper custom resolver throws null exception in DependencyResolverInitialization.

Vote:
 

Hi,

We are using AutoMapper in our Commerce site. While mapping from the custom model to an EPiServer Model(VariationContent) throws a below error. 

Adding to that vice versa works properly. Also  In version 10.2.1 works well, but not in 12.4.

I have mentioned the codes below with an error.

 cfg.CreateMap()
                    .ForMember(dest => dest.Orientation, opt => opt.Ignore())
                    .ForMember(dest => dest.Series, opt => opt.Ignore())
                     .ForMember(dest => dest.Tested, opt => opt.Ignore())
                    .ForMember(dest => dest.Rotation, opt => opt.Ignore())
                    .ForMember(dest => dest.Material, opt => opt.Ignore())
                    .IgnoreAllNonExistingProperties();
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Stack Trace: 


[NullReferenceException: Object reference not set to an instance of an object.]
   EPiServer.Commerce.Catalog.DataAnnotations.ValidUrlAttribute..ctor(LocalizationService localizationService, UrlSegmentOptions urlSegmentOptions) +67
   EPiServer.Commerce.Catalog.DataAnnotations.ValidUrlAttribute..ctor() +76
   System.RuntimeTypeHandle.CreateCaInstance(RuntimeType type, IRuntimeMethodInfo ctor) +0
   System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes, Boolean isDecoratedTargetSecurityTransparent) +1471
   System.Reflection.CustomAttribute.GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType) +106
   System.Reflection.RuntimePropertyInfo.GetCustomAttributes(Boolean inherit) +37
   AutoMapper.Configuration.MappingExpression`2.Configure(TypeMap typeMap) +122
   AutoMapper.ProfileMap.BuildTypeMap(IConfigurationProvider configurationProvider, ITypeMapConfiguration config) +65
   AutoMapper.ProfileMap.Register(IConfigurationProvider configurationProvider) +75
   AutoMapper.MapperConfiguration.Seal() +151
   AutoMapper.MapperConfiguration..ctor(MapperConfigurationExpression configurationExpression) +764
   AutoMapper.MapperConfiguration..ctor(Action`1 configure) +23
   SnS.Infrastructure.DependencyResolverInitialization.GetMappingConfiguration() in D:\Phase13-upgrading\src\SnS\Infrastructure\DependencyResolverInitialization.cs:195
   SnS.Infrastructure.DependencyResolverInitialization.ConfigureContainer(ConfigurationExpression container) in D:\Phase13-upgrading\src\SnS\Infrastructure\DependencyResolverInitialization.cs:190
   StructureMap.PipelineGraph.Configure(Action`1 configure) +97
   StructureMap.Container.Configure(Action`1 configure) +93
   SnS.Infrastructure.DependencyResolverInitialization.ConfigureContainer(ServiceConfigurationContext context) in D:\Phase13-upgrading\src\SnS\Infrastructure\DependencyResolverInitialization.cs:70
   EPiServer.Framework.Initialization.Internal.<>c__DisplayClass4_0.b__0() +16
   EPiServer.Framework.Initialization.Internal.ModuleNode.Execute(Action a, String key) +52
   EPiServer.Framework.Initialization.Internal.ModuleNode.ConfigureContainer(ServiceConfigurationContext context) +100
   EPiServer.Framework.Initialization.InitializationEngine.ConfigureCurrentModules(Boolean final) +177
   EPiServer.Framework.Initialization.InitializationEngine.ExecuteTransition(Boolean continueTransitions) +115
   EPiServer.Framework.Initialization.InitializationEngine.Initialize() +40
   EPiServer.Framework.Initialization.<>c.b__7_0(InitializationEngine e) +9
   EPiServer.Framework.Initialization.InitializationModule.EngineExecute(HostType hostType, Action`1 engineAction) +338
   EPiServer.Framework.Initialization.InitializationModule.FrameworkInitialization(HostType hostType) +170
   EPiServer.Global..ctor() +43
   SnS.EPiServerApplication..ctor() +42
   ASP.global_asax..ctor() in c:\Users\User\AppData\Local\Temp\Temporary ASP.NET Files\root\d16a9737\21107c38\App_global.asax.0.cs:0

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +119
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
   System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark) +1117
   System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes) +124
   System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture) +20
   System.Web.HttpRuntime.CreateNonPublicInstance(Type type, Object[] args) +59
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +287
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +303

[HttpException (0x80004005): Exception has been thrown by the target of an invocation.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +772
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +95
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +195

Please help me out,

Advance thanks,

regards,

Karthik

#195406
Jul 24, 2018 10:59
Vote:
 

Hi

I'm no automapper expert, but by looking at the stack trace it looks like the ValidUrlAttribute constructor is called before the IoC container has been configured. And for the default constructor on ValidUrlAttribute to work, it needs the container to be configured. If it isn't, you need to use the constructor with takes two services as arguments, and pass those on explicitly.

Now, I understand that it is automapper who does this call, and not you explicitly. But would it be possible to do this logic later in the initialization, when the container is all setup and ready to be used?

Regards

Per Gunsarfs

#195415
Jul 24, 2018 13:40
Vote:
 

Can you post your DependencyResolverInitialization class here? 

#195425
Jul 24, 2018 16:50
Vote:
 

Thank you team,

Quan,

Below is out code.we have faced some issues regarding the web API route registration so registered directly in dependency module instead of app_start. The commented line of code has a problem.

    [InitializableModule]
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class DependencyResolverInitialization : IConfigurableModule
    {
        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.StructureMap().Configure(ConfigureContainer);
            var dependencyResolver = new StructureMapDependencyResolver(context.StructureMap());
            DependencyResolver.SetResolver(dependencyResolver); ////mvc
            GlobalConfiguration.Configure(config =>
            {
                WebApiConfig.Register(config);
                config.Services.Add(typeof(IExceptionLogger), new WebApiExceptionLogger());
            });
            GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver; ////web api
        }

        public void Initialize(InitializationEngine context)
        {
        }

        public void Uninitialize(InitializationEngine context)
        {
        }

        public void Preload(string[] parameters)
        {
        }

        private static void ConfigureContainer(ConfigurationExpression container)
        {
            container.Scan(opt =>
            {
                opt.TheCallingAssembly();
                opt.WithDefaultConventions();
                opt.LookForRegistries();
            });

            container.For<UserManager<ApplicationUser>>()
                    .Use(() => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
                    .SetLifecycleTo(new UniquePerRequestLifecycle());

            container.For<RoleManager<IdentityRole>>()
                .Use(() => new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext())))
                .SetLifecycleTo(new UniquePerRequestLifecycle());

            container.For<ICacheServiceFactory>()
                .Use(() => new CacheServiceFactory(HttpContext.Current));

            container.For<ICustomerRepository>().Use<CustomerRepository>();
            container.For<IWLCUsersRepository>().Use<WLCUsersRepository>();
            container.For<IUnitOfWork>().Use<UnitOfWork>();
            container.For<SnsDbContext>().HybridHttpOrThreadLocalScoped().Use<SnsDbContext>();
            container.For(typeof(IRepository<>)).Use(typeof(GenericRepository<>));
            container.For<IMapper>().Use(new Mapper(GetMappingConfiguration()));
        }

        private static MapperConfiguration GetMappingConfiguration()
        {
            var mapperConfiguration =
             new MapperConfiguration(cfg =>
            {
                cfg.ConstructServicesUsing(type => ServiceLocator.Current.GetInstance(type));

                cfg.CreateMap<string, IndexSearchableStringsArray>()
                    .ForMember(x => x.Value, opt => opt.MapFrom(src => src == null ? null : src.Split(',').Where(x => !string.IsNullOrEmpty(x)).Select(x => x.Trim())))
                    .ForMember(x => x.SearchTerm, opt => opt.MapFrom(src => src == null ? null : src.Split(',').Where(x => !string.IsNullOrEmpty(x)).Select(x => SearchHelper.RemoveSpecialSearchCharacters(x, false).Trim())))
                    .ForMember(x => x.Values, opt => opt.MapFrom(src => SearchHelper.GetSearchableValuesString(src)));

                cfg.CreateMap<string, IndexSearchableString>()
                    .ForMember(x => x.SearchTerm, opt => opt.MapFrom(x => SearchHelper.RemoveSpecialSearchCharacters(x, false)))
                    .ForMember(x => x.Value, opt => opt.MapFrom(x => x));

                cfg.CreateMap<OrderResponseListItem, SnSOrderListViewModel>()
                    .ForMember(dest => dest.OrderDateTime, opt => opt.MapFrom(src => src.OrderDateTime.ToString("dd-MMM-yyyy")));

                cfg.CreateMap<EpiOrderResponseListItem, WLC.Models.ViewModels.WLCOrderListViewModel>()
                    .ForMember(dest => dest.OrderDateTime, opt => opt.MapFrom(src => src.OrderDateTime.ToString("dd-MMM-yyyy")));

                cfg.CreateMap<OrderResponseDetail, OrderDetailPageViewModel>()
                    .ForMember(x => x.Items, order => order.Ignore())
                    .IgnoreAllNonExistingProperties();

                cfg.CreateMap<OrderResponseDetail, WLC.Models.ViewModels.WLCOrderDetailPageViewModel>()
                    .ForMember(x => x.Items, order => order.Ignore())
                    .IgnoreAllNonExistingProperties();

                cfg.CreateMap<OrderResponseDetailPart, SnSOrderDetailItemViewModel>()
                    .IgnoreAllNonExistingProperties();

                cfg.CreateMap<OrderResponseDetailPart, WLC.Models.ViewModels.WLCOrderDetailItemViewModel>()
                    .IgnoreAllNonExistingProperties();

                //// cfg.CreateMap<ImportProductData, Variation>()
                ////    .ForMember(dest => dest.Orientation, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Series, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Tested, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Rotation, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Material, opt => opt.Ignore())
                ////    .IgnoreAllNonExistingProperties();

                cfg.CreateMap<Variation, ExportProductData>()
                .ForMember(x => x.Orientation, opt => opt.MapFrom(src => EnumValues.Convert<OrientationOptionsEnum>(src.Orientation)))
                .ForMember(x => x.Series, opt => opt.MapFrom(src => EnumValues.Convert<SeriesOptionsEnum>(src.Series)))
                .ForMember(x => x.Tested, opt => opt.MapFrom(src => EnumValues.Convert<TestedOptionsEnum>(src.Tested)))
                .ForMember(x => x.Rotation, opt => opt.MapFrom(src => EnumValues.Convert<RotationOptionsEnum>(src.Rotation)))
                .ForMember(x => x.Material, opt => opt.MapFrom(src => EnumValues.Convert<MaterialOptionsEnum>(src.Material)))
                .ForMember(x => x.Specifications3, opt => opt.MapFrom(src => src.Applications))
                .IgnoreAllNonExistingProperties();
				}
				

Thanks and Regards,

Karthik.

#195433
Jul 25, 2018 8:46
Vote:
 

It seems to me that at that point there is no registration for UrlSegmentOptions

if you add context.Locate.Advanced.GetInstance<UrlSegmentOptions>(); inside Initialize, what does it return?

If it returns null, then you might try to add it 

context.Services.AddSingleton(s => new UrlSegmentOptions
{
SupportIriCharacters = true,
ValidCharacters = @"\p{L}0-9\-_~\.\$"
});

#195434
Jul 25, 2018 9:11
Vote:
 

Thanks for your quick reply Quan,

I tried this both but getting the same error.

#195435
Jul 25, 2018 9:34
Vote:
 

What does your DependencyResolverInitialization look like now:

#195436
Jul 25, 2018 9:35
Vote:
 
 public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.StructureMap().Configure(ConfigureContainer);
            var dependencyResolver = new StructureMapDependencyResolver(context.StructureMap());
            DependencyResolver.SetResolver(dependencyResolver); ////mvc            
            GlobalConfiguration.Configure(config =>
            {
                WebApiConfig.Register(config);
                config.Services.Add(typeof(IExceptionLogger), new WebApiExceptionLogger());
            });
            GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver; ////web api
        }

        public void Initialize(InitializationEngine context)
        {
            context.Locate.Advanced.GetInstance<UrlSegmentOptions>();
        }
#195438
Jul 25, 2018 9:42
Vote:
 

sealed. please re-read my post carefully. 

#195439
Jul 25, 2018 9:44
Vote:
 

Hi Quan,

 We are calling our mapper set up inside the below method.

public void ConfigureContainer(ServiceConfigurationContext context)

{

}

We can't hit the Initialization method since the Custom Model class to EPiServer Model class mapping throws an exception which calls inside the ConfigureContainer. If we commented out the below mapper set up we can get a value(non Null) for the context.Locate.Advanced.GetInstance<UrlSegmentOptions>() in Initialization call.

 //// cfg.CreateMap<ImportProductData, Variation>()
                ////    .ForMember(dest => dest.Orientation, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Series, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Tested, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Rotation, opt => opt.Ignore())
                ////    .ForMember(dest => dest.Material, opt => opt.Ignore())
                ////    .IgnoreAllNonExistingProperties();

We also try to Initialize the URLSegmentOption before the mapper set up did not help us.

public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Services.AddSingleton(s => new UrlSegmentOptions
{
SupportIriCharacters = true,
ValidCharacters = @"\p{L}0-9\-_~\.\$"
});
context.StructureMap().Configure(ConfigureContainer); // Mappers setup call
var dependencyResolver = new StructureMapDependencyResolver(context.StructureMap());
DependencyResolver.SetResolver(dependencyResolver); ////mvc
GlobalConfiguration.Configure(config =>
{
WebApiConfig.Register(config);
config.Services.Add(typeof(IExceptionLogger), new WebApiExceptionLogger());
});

GlobalConfiguration.Configuration.DependencyResolver = dependencyResolver; ////web api
}

#195440
Jul 25, 2018 10:09
Vote:
 

My bad, I should be more clear, when I talked about adding this code

context.Services.AddSingleton(s => new UrlSegmentOptions
{
SupportIriCharacters = true,
ValidCharacters = @"\p{L}0-9\-_~\.\$"
});



I meant ConfigureContainer, before 

            context.StructureMap().Configure(ConfigureContainer);
#195442
Edited, Jul 25, 2018 10:11
Vote:
 

Thanks Quan,

Sorry for the late reply.I am not able to get you. Please explain what to do.

#195541
Jul 27, 2018 19:13
Vote:
 

which automapper version are you using?

#195582
Jul 31, 2018 7:03
Vote:
 

Hi valdis iljuconoks,

we are using below one

<package id="AutoMapper" version="7.0.1" targetFramework="net461" />

#195585
Jul 31, 2018 9:05
Vote:
 

how to bypass this issue inn some other way?

Advance thanks 

#195923
Aug 12, 2018 10:23
Vote:
 

I have the exact same problem. How did you solve it? I tried the suggestions in this thread without success.

#201993
Mar 11, 2019 14:44
Vote:
 

I am not able to resolve the issue(when registering in the dependency module). So i used like below one

        private IMapper Map
        {
            get { return map ?? (map = CreateMap()); }
        }

        private IMapper CreateMap()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<ImportProductData, Variation>()
                    .ForMember(dest => dest.Orientation, opt => opt.Ignore())
                    .IgnoreAllNonExistingProperties();
            });
            return config.CreateMapper();
        }
#201994
Edited, Mar 11, 2019 15:30
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.