Handling IoC configuration - upgrade .NET 6

Vote:
 

Hello,

I have been struggling for some time with the topic of migrating the EpiServer CMS & Commerce project from version 
11 to 12 and 
13 to 14 
and thus moving from the .NET Framework to .NET 6.


I am currently trying to configure Dependency Injection appropriately, however I am getting a strange error as shown in the attached image. What could this be due to?

System.InvalidOperationException: There is no service registered for EPiServer.Construction.IContentFactory
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.RegisterInterceptor[TService](IServiceCollection services, Func`3 interceptorFactory, Boolean tryAdd)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.Intercept[TService](IServiceCollection services, Func`3 interceptorFactory)
   at EPiServer.Commerce.Initialization.InitializationModule.<>c.<ConfigureContainer>b__8_4(Object o, ServiceConfigurationEventArgs e)
   at EPiServer.ServiceLocation.ServiceConfigurationContext.RaiseConfigurationComplete()
   at EPiServer.Framework.Initialization.InitializationEngine.ConfigureCurrentModules(Boolean final)
   at EPiServer.Framework.Initialization.InitializationEngine.ExecuteTransition(Boolean continueTransitions)
   at EPiServer.Framework.Initialization.InitializationEngine.Configure()
   at EPiServer.DependencyInjection.ServiceLocatorProviderFactoryFacade`1.CreateBuilder(IServiceCollection services)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateBuilder(IServiceCollection services)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at X.Web.Program.Main(String[] args) in C:\00_Projects\X\X.Web\Program.cs:line 5

here is my Startup.cs file

public class Startup
{
    private readonly IWebHostEnvironment _webHostingEnvironment;

    public Startup(IWebHostEnvironment webHostingEnvironment)
    {
        _webHostingEnvironment = webHostingEnvironment;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        if (_webHostingEnvironment.IsDevelopment())
        {
            AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(_webHostingEnvironment.ContentRootPath, "App_Data"));

            services.Configure<SchedulerOptions>(options => options.Enabled = false);
        }

        services
            .AddCmsAspNetIdentity<ApplicationUser>()
            .AddCms()
            .AddCommerce()
            .AddAdminUserRegistration()
            .AddEmbeddedLocalization<Startup>();

        // Required by Wangkanai.Detection
        services.AddDetection();

        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
            options.Cookie.IsEssential = true;
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // Required by Wangkanai.Detection
        app.UseDetection();
        app.UseSession();

        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapContent();
        });
    }
}

Any tips will be great help to me, thanks!

Wojciech

#287528
Edited, Sep 16, 2022 14:09
Vote:
 

Do you get any warnings when you run dotnet restore? Seems like you're missing dependencies/assemblies.

#287593
Edited, Sep 17, 2022 7:30
Vote:
 

Hi 

 I noticed in your ConfigureServices method, you have both AddCms() and AddCommerce(). Is your solution CMS or Commerce? You only need to call one of these. E.g. if it's commerce, remove "AddCms()". 

What's your program.cs file look like? In your stack trace, it mentioned line 5

#287662
Sep 19, 2022 2:11
Vote:
 

Hi

It sounds like one of the calls from startup is trying to use IContentFactory but its not configured for DI. You might need to register it under ConfigureServices.

#287741
Sep 20, 2022 16:56
Vincent - Sep 21, 2022 1:57
IContentFactory is registered in CmsRuntimeInitialization module.
Vote:
 

Hi Wojciech,

Can't see anything unusual with your startup.cs.

Any chance we could also inspect your program.cs ? I'm assuming that's where you're calling the host builder?

#287791
Sep 21, 2022 8:09
Vote:
 

Hello everyone, thanks for your answers. Unfortunately, it still does not work as it should. 

here's my Program.cs file,

namespace TRM.Web;

public class Program
{
    public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureCmsDefaults()
            .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}

error from 8 line comes from:

public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();

Johan Petersson in the meantime I solved many issues with dependencies and now I no longer get any warnings after running the dotnet restore command.

after resolving all warnings, it still receives the same error as before:

System.InvalidOperationException: There is no service registered for EPiServer.Construction.IContentFactory
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.RegisterInterceptor[TService](IServiceCollection services, Func`3 interceptorFactory, Boolean tryAdd)
   at Microsoft.Extensions.DependencyInjection.ServiceCollectionExtensions.Intercept[TService](IServiceCollection services, Func`3 interceptorFactory)
   at EPiServer.Commerce.Initialization.InitializationModule.<>c.<ConfigureContainer>b__8_4(Object o, ServiceConfigurationEventArgs e)
   at EPiServer.ServiceLocation.ServiceConfigurationContext.RaiseConfigurationComplete()
   at EPiServer.Framework.Initialization.InitializationEngine.ConfigureCurrentModules(Boolean final)
   at EPiServer.Framework.Initialization.InitializationEngine.ExecuteTransition(Boolean continueTransitions)
   at EPiServer.Framework.Initialization.InitializationEngine.Configure()
   at EPiServer.DependencyInjection.ServiceLocatorProviderFactoryFacade`1.CreateBuilder(IServiceCollection services)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateBuilder(IServiceCollection services)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at TRM.Web.Program.Main(String[] args) in C:\00_Projects\TRM\TRM.Web\Program.cs:line 8

any new ideas, what is wrong?

#287800
Sep 21, 2022 14:46
Vote:
 

It's almost as if the Commerce Initialization module is intercepting the default implementation of IContentFactory but its not registered yet. Where IContactFactory default impl is registered in the CmsInitialization

 at EPiServer.ServiceLocation.ServiceConfigurationContext.RaiseConfigurationComplete() <-- Event Raised Here
at EPiServer.Commerce.Initialization.InitializationModule.<>c.<ConfigureContainer>b__8_4(Object o, ServiceConfigurationEventArgs e) <-- Attempting to intercept default impl IContentFactory but implodes instead

Would it be possible to see what packages you've installed? Would be better to see a screenshot of whats in your packagereference in csproj.

#287801
Edited, Sep 21, 2022 15:36
Vote:
 

Just comparing your Startup.cs with a from-scratch Commerce project, I see that services.AddMvc(); is missing. I'm not sure if that's the issue, but it's something I noted. Your Program.cs file looks fine.

Looking at the Commerce initialization module (found in the EPiServer.Business.Commerce assembly), it does have a dependency on CmsRuntimeInitialization, which is what registers the IContentFactory service. So nothing looks out of place there.

If you're still having troubles, try creating a from-scratch Commerce project, and just compare everything between the two.

#287802
Sep 21, 2022 15:38
Vote:
 

Hello Chris & Surjit

unfortuneatly I'm not able to upload phots in that case here's my csproj file:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <Nullable>disable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <AssemblyVersion>1.2.0.0</AssemblyVersion>
    <FileVersion>1.2.0.0</FileVersion>
  </PropertyGroup>

  <ItemGroup>
    <Using Include="EPiServer" />
    <Using Include="EPiServer.Core" />
    <Using Include="EPiServer.DataAbstraction" />
    <Using Include="EPiServer.DataAnnotations" />
  </ItemGroup>
  
  <ItemGroup>
    <PackageReference Include="EPiServer.AddOns.Helpers" Version="1.1.0" />
    <PackageReference Include="EPiServer.CMS" Version="12.11.0" />
    <PackageReference Include="EPiServer.CMS.AspNetCore" Version="12.9.2" />
    <PackageReference Include="EPiServer.CMS.AspNetCore.HtmlHelpers" Version="12.9.2" />
    <PackageReference Include="EPiServer.CMS.AspNetCore.Templating" Version="12.9.2" />
    <PackageReference Include="EPiServer.CMS.Core" Version="12.9.2" />
    <PackageReference Include="EPiServer.Commerce" Version="14.5.0" />
    <PackageReference Include="EPiServer.Commerce.Core" Version="14.5.0" />
    <PackageReference Include="EPiServer.Find" Version="14.1.0" />
    <PackageReference Include="EPiServer.Find.Cms" Version="14.1.0" />
    <PackageReference Include="EPiServer.Find.Commerce" Version="12.1.1" />
    <PackageReference Include="EPiServer.Framework" Version="12.9.2" />
    <PackageReference Include="EPiServer.Framework.AspNetCore" Version="12.9.2" />
    <PackageReference Include="EPiServer.Hosting" Version="12.9.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0-rc.1.22426.7" />
    <PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
    <PackageReference Include="RestSharp" Version="108.0.2" />
    <PackageReference Include="System.Linq.Async" Version="6.0.1" />
    <PackageReference Include="Wangkanai.Detection" Version="5.2.0" />
  </ItemGroup>
  
  <ItemGroup>
    <Folder Include="Business\Factories" />
    <Folder Include="Business\ScheduleJobs" />
    <Folder Include="Extensions\" />
    <Folder Include="Helpers\" />
    <Folder Include="Models\ViewModels\AutoInvest" />
  </ItemGroup>
  
  <ItemGroup>
    <ProjectReference Include="..\GoogleProductFeed\TRM.ProductFeeds.csproj" />
    <ProjectReference Include="..\Hephaestus.ContentTypes\Hephaestus.ContentTypes.csproj" />
    <ProjectReference Include="..\Hephaestus.XmlSitemaps2\Hephaestus.XmlSitemaps2.csproj" />
    <ProjectReference Include="..\Kyc.Core\Kyc.Core.csproj" />
    <ProjectReference Include="..\PricingAndTradingService\PricingAndTradingService.csproj" />
    <ProjectReference Include="..\TRM.IntegrationServices\TRM.IntegrationServices.csproj" />
    <ProjectReference Include="..\TRM.Shared\TRM.Shared.csproj" />
  </ItemGroup>
</Project>

besides, I did as you said Chris, I copied the configuration from the pure Commerce project and now getting another error.

System.InvalidOperationException: No service for type 'EPiServer.ServiceLocation.IRootServiceScopeFactory' has been registered.
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at EPiServer.ServiceLocation.ServiceProviderExtensions.GetInstance[TService](IServiceProvider serviceProvider)
   at EPiServer.DependencyInjection.ServiceLocatorProviderFactoryFacade`1.CreateServiceProvider(TContainerBuilder containerBuilder)
   at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
   at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
   at Microsoft.Extensions.Hosting.HostBuilder.Build()
   at TRM.Web.Program.Main(String[] args) in C:\00_Projects\TRM\TRM.Web\Program.cs:line 5

that above error is given for the following configuration

public class Startup
{
    private readonly IWebHostEnvironment _webHostingEnvironment;

    public Startup(IWebHostEnvironment webHostingEnvironment)
    {
        _webHostingEnvironment = webHostingEnvironment;
    }

    //commerceCore-Template
    public void ConfigureServices(IServiceCollection services)
    {
        if (_webHostingEnvironment.IsDevelopment())
        {
            AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(_webHostingEnvironment.ContentRootPath, "App_Data"));

            services.Configure<SchedulerOptions>(options => options.Enabled = false);
        }

        services.AddMvc();
        
        services
            .AddCmsAspNetIdentity<ApplicationUser>()
            .AddCommerce()
            .AddAdminUserRegistration()
            .AddEmbeddedLocalization<Startup>();
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseAnonymousId();

        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapContent();
        });
    }
namespace TRM.Web;

public class Program
{
    public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureCmsDefaults()
            .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
}

I also have an InitlizationModule which contains the IoC configuration, here's an example piece of its code

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Commerce.Initialization.InitializationModule))]
public class CustomizedRenderingInitialization : IConfigurableModule
{
    public void ConfigureContainer(ServiceConfigurationContext context)
    {
        // Implementations for custom interfaces can be registered here.
        context.ConfigurationComplete += (o, e) =>
        {
            var services = context.Services;
            services.AddScoped<IAmNavigationHelper, NavigationHelper>();
            //...
            //...
            //...
            services.AddScoped<IAmCartHelper, CartHelper>();
        };
    }
    public void Initialize(InitializationEngine context) { }
    public void Uninitialize(InitializationEngine context) { }
}

I wonder if I am one step ahead or if I have regressed in my trying to. Which is strange for a pure commerce project everything works without any problems, I have no idea what I am doing wrong.

#287886
Sep 22, 2022 12:24
Vote:
 

Can you try adding AddFind() after .AddCommerce()

Since you have Episerver.Find packages installed

#287887
Sep 22, 2022 13:16
Vote:
 

It would be also interesting to know if any projects in the your solution has additional InitializationModules or ConfigurableModules. See what the moduledependency on those are.

CustomizedRenderingInitialization has a dependency on the Commerce initializationModule..and that's where the older exception was being thrown so I doubt that is an issue.

#287888
Sep 22, 2022 13:19
* 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.