DryIoc: Using DryIoc causes Blazor to crash

Hello,

When I try to use DryIoc in my Server-size Blazor project, it causes an internal Blazor error.

To reproduce:

  1. Create new Server-side Blazor project.
  2. Install DryIoc.Microsoft.DependencyInjection and Serilog.AspNetCore (needed to see the error)
  3. Replace Program.cs:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using BlazorApp2.Data;
using DryIoc;
using DryIoc.Microsoft.DependencyInjection;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

var container = new Container(
    Rules.Default.With(
        FactoryMethod.ConstructorWithResolvableArguments,
        propertiesAndFields: PropertiesAndFields.Auto)
);

// Here it goes the integration with the existing DryIoc container
var diFactory = new DryIocServiceProviderFactory(container);

builder.Host.UseServiceProviderFactory(diFactory);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(options =>
{
    options.DetailedErrors = true;
});

var logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .ReadFrom.Configuration(builder.Configuration)
    .Enrich.FromLogContext()
    .WriteTo.File("Errors/Log_.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Host.UseSerilog(logger);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();
  1. Run the app and observe that after a few seconds “An unhandled exception has occurred. See browser dev tools for details.” pops up.
  2. Open the generated log file to see the actual error:
2023-04-11 17:34:13.636 -04:00 [DBG] Created circuit zhg1kxyMHSMJkpwgLDEyfzYDVTLQGwD-2VCPcN7QgIY for connection fShBxz1E2UjLoN7J1mkatg
2023-04-11 17:34:16.732 -04:00 [DBG] Circuit initialization failed
DryIoc.ContainerException: code: Error.WaitForScopedServiceIsCreatedTimeoutExpired;
message: DryIoc has waited for the creation of the scoped or singleton service by the "other party" for the 3000 ticks without the completion. 
You may call `exception.TryGetDetails(container)` to get the details of the problematic service registration.
The error means that either the "other party" is the parallel thread which has started but is unable to finish the creation of the service in the provided amount of time. 
Or more likely the "other party"  is the same thread and there is an undetected recursive dependency or 
the scoped service creation is failed with the exception and the exception was catched but you are trying to resolve the failed service again. 
For all those reasons DryIoc has a timeout to prevent the infinite waiting. 
You may change the default timeout via `Scope.WaitForScopedServiceIsCreatedTimeoutTicks=NewNumberOfTicks`
   at DryIoc.ContainerException.WithDetails(Object details, Int32 error, Object arg0, Object arg1, Object arg2, Object arg3) in /_/src/DryIoc/Container.cs:line 14161
   at DryIoc.Throw.WithDetails(Object details, Int32 error, Object arg0, Object arg1, Object arg2, Object arg3) in /_/src/DryIoc/Container.cs:line 14554
   at DryIoc.Scope.WaitForItemIsSet(ImMapEntry`1 itemRef) in /_/src/DryIoc/Container.cs:line 13031
   at DryIoc.Interpreter.InterpretGetScopedOrSingletonViaFactoryDelegate(IResolverContext r, GetScopedOrSingletonViaFactoryDelegateExpression e, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs) in /_/src/DryIoc/Container.cs:line 3793
   at DryIoc.Interpreter.TryInterpretMethodCall(IResolverContext r, MethodCallExpression callExpr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3481
   at DryIoc.Interpreter.TryInterpret(IResolverContext r, Expression expr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3149
   at DryIoc.Interpreter.TryInterpretAndUnwrapContainerException(IResolverContext r, Expression expr, Object& result) in /_/src/DryIoc/Container.cs:line 3015
   at DryIoc.Container.ResolveAndCache(Int32 serviceTypeHash, Type serviceType, IfUnresolved ifUnresolved) in /_/src/DryIoc/Container.cs:line 435
   at DryIoc.Container.System.IServiceProvider.GetService(Type serviceType) in /_/src/DryIoc/Container.cs:line 338
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ComponentServiceCollectionExtensions.<>c.<AddServerSideBlazor>b__0_1(IServiceProvider s)
   at DryIoc.Registrator.ToFactoryDelegate[TService](Func`2 f, IResolverContext r) in /_/src/DryIoc/Container.cs:line 7967
   at DryIoc.Interpreter.InterpretGetScopedOrSingletonViaFactoryDelegate(IResolverContext r, GetScopedOrSingletonViaFactoryDelegateExpression e, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs) in /_/src/DryIoc/Container.cs:line 3799
   at DryIoc.Interpreter.TryInterpretMethodCall(IResolverContext r, MethodCallExpression callExpr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3481
   at DryIoc.Interpreter.TryInterpret(IResolverContext r, Expression expr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3149
   at DryIoc.Interpreter.TryInterpret(IResolverContext r, Expression expr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3196
   at DryIoc.Interpreter.InterpretGetScopedOrSingletonViaFactoryDelegate(IResolverContext r, GetScopedOrSingletonViaFactoryDelegateExpression e, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs) in /_/src/DryIoc/Container.cs:line 3800
   at DryIoc.Interpreter.TryInterpretMethodCall(IResolverContext r, MethodCallExpression callExpr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3481
   at DryIoc.Interpreter.TryInterpret(IResolverContext r, Expression expr, IParameterProvider paramExprs, Object paramValues, ParentLambdaArgs parentArgs, Object& result) in /_/src/DryIoc/Container.cs:line 3149
   at DryIoc.Interpreter.TryInterpretAndUnwrapContainerException(IResolverContext r, Expression expr, Object& result) in /_/src/DryIoc/Container.cs:line 3015
   at DryIoc.Container.ResolveAndCache(Int32 serviceTypeHash, Type serviceType, IfUnresolved ifUnresolved) in /_/src/DryIoc/Container.cs:line 435
   at DryIoc.Container.System.IServiceProvider.GetService(Type serviceType) in /_/src/DryIoc/Container.cs:line 338
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.AspNetCore.Components.Server.Circuits.CircuitFactory.CreateCircuitHostAsync(IReadOnlyList`1 components, CircuitClientProxy client, String baseUri, String uri, ClaimsPrincipal user, IPersistentComponentStateStore store)
   at Microsoft.AspNetCore.Components.Server.ComponentHub.StartCircuit(String baseUri, String uri, String serializedComponentRecords, String applicationState)

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 19 (11 by maintainers)

Commits related to this issue

Most upvoted comments

@MaxwellDAssistek Thank you very much, I saw the details on #547.

@MaxwellDAssistek Don’t do this 😃 Yeah, the internal is good for authors to avoid breaking changes, but hard for user hacking. Ok, I will try to re-create the app and update you later.

@dadhi Still no luck unfortunately. I still get the same exception with the following Program.cs:

using BlazorApp2;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using BlazorApp2.Data;
using DryIoc;
using DryIoc.Microsoft.DependencyInjection;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

var container = new Container(
    Rules.MicrosoftDependencyInjectionRules.With(
        FactoryMethod.ConstructorWithResolvableArguments,
        propertiesAndFields: PropertiesAndFields.Auto)
);
Globals.MainContainer = container;

// Here it goes the integration with the existing DryIoc container
var diFactory = new DryIocServiceProviderFactory(container, RegistrySharing.Share);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor(options =>
{
    options.DetailedErrors = true;
});
builder.Services.AddSingleton<WeatherForecastService>();

var logger = new LoggerConfiguration()
    .MinimumLevel.Verbose()
    .ReadFrom.Configuration(builder.Configuration)
    .Enrich.FromLogContext()
    .WriteTo.File("Errors/Log_.txt", rollingInterval: RollingInterval.Day)
    .CreateLogger();

builder.Host.UseSerilog(logger);

builder.Host.UseServiceProviderFactory(diFactory);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();