Error getting IContextModeResolver in IOC container

ZZ
ZZ
Vote:
 

Hi,

I am in process of upgrading from EPIServer 11 to Optmizely Content Cloud 12 (.NET 6) and in which I have got this error -> 

System.InvalidOperationException
  HResult=0x80131509
  Message=No service for type 'EPiServer.Web.IContextModeResolver' has been registered.
 

I need ContextMode to differentiate between Subdata client and real client which are then injected in controllers-> 

using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using EPiServer.Web;

namespace XX.Business.Initialization
{
    [ModuleDependency(typeof(ServiceContainerInitialization), typeof(InitializationModule))]

    public class DependencyInjection : IConfigurableModule
    {
        public void Initialize(InitializationEngine context)
        {
            throw new NotImplementedException();
        }

        public void Uninitialize(InitializationEngine context)
        {
            throw new NotImplementedException();
        }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {
       // This line is throwing an error
         var contextModeResolver = ServiceLocator.Current.GetInstance<IContextModeResolver>();

        //    context.Services.AddTransient<ICorClient>(l =>
        //    {
        //        if (contextModeResolver.CurrentMode.EditOrPreview()) return new CorClientStub();
        //        return new CorClient(l.GetInstance<HttpClient>());
        //    });

        }
    }
}

I could also have this in startup.cs but even there I would need contextMode.

Any help would be appreciated.

#291901
Edited, Nov 18, 2022 15:28
Vote:
 

Pretty sure ServiceLocator.Current is not available yet becuase it is still doing initialization.  You should use

context.Locate.Advanced.GetInstance<IContextModeResolver>

I also think you need to make sure it has been intialized by adding module dependency

[ModuleDependency(typeof(EPiServer.Initialization.CmsCoreInitialization))]
#291904
Nov 18, 2022 17:07
Vote:
 

Your code example is weird. You are trying to fetch the instance of IContextModeResolver in ConfigureContainer - the method that's used to build up the service locator. It would be more reasonable to fetch that instance in the Initialize method, if anything, when the service locator is ready to use.

You have at least two options to override IContextModeResolver - either use StructureMap and For<IContextModeResolver>().DecorateAllWith<T>(...) or you can replace the registered resolver of IContextModeResolver using context.ConfigurationComplete += (sender, args) => { context.Services.RemoveAll<IContextModeResolver>; context.Services.AddTransient<IContextModeResolver, CustomContextModeResolver>(); }.

#292023
Nov 21, 2022 14:37
ZZ
Vote:
 

I did it exactly as Mark told above in the comments & its working perfectly fine. This is the final version of the code -> 

[ModuleDependency(typeof(ServiceContainerInitialization), typeof(EPiServer.Initialization.CmsCoreInitialization), typeof(InitializationModule))]
    public class DependencyInjection : IConfigurableModule
    {
        public static IContextModeResolver contextModeResolver { get; set; }
        public void Initialize(InitializationEngine context)
        {
            contextModeResolver = context.Locate.Advanced.GetRequiredService<IContextModeResolver>();
        }

        public void Uninitialize(InitializationEngine context)
        {
            throw new NotImplementedException();
        }

        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.AddTransient<ICorClient>(l =>
            {
                if (contextModeResolver.CurrentMode.EditOrPreview()) return new CorClientStub();
                return new CorClient(l.GetInstance<HttpClient>());
            });
}
}
#292027
Nov 21, 2022 15:40
* 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.