fairybread: Cannot resolved scope service ... from root provider
Describe the bug I receive the following error when performing a mutation with a validator attached.
Removing .AddFairyBread()
fixes the error but that’s obviously not the desired result.
Hot Chocolate setup:
services
.AddGraphQLServer()
.AddQueryType()
.AddTypeExtension<UserQueries>()
.AddTypeExtension<ClassroomQueries>()
.AddMutationType()
.AddTypeExtension<ClassroomMutations>()
.AddTypeExtension<AuthMutations>()
.AddType<UserType>()
.AddType<ClassroomType>()
.EnableRelaySupport()
.AddDataLoader<UserByIdDataLoader>()
.AddDataLoader<ClassroomByIdDataLoader>()
.AddAuthorization()
.AddFairyBread();
Services:
services.AddPooledDbContextFactory<ApplicationDbContext>(opt => {
opt.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"));
opt.UseSnakeCaseNamingConvention();
});
services.AddScoped(p =>
p.GetRequiredService<IDbContextFactory<ApplicationDbContext>>()
.CreateDbContext());
services.AddValidatorsFromAssemblyContaining<Startup>();
services.AddHotChocolateServices();
services.AddIdentityServices();
Versions:
- FairyBread: v6.0.0
- HotChocolate: v11.1.0
- FluentValidation: v10.0.4
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 20 (11 by maintainers)
Commits related to this issue
- Fixing resolution of scoped services. Addresses #43 — committed to benmccallum/fairybread by benmccallum 3 years ago
I’ve tested this today both in my own reproducible, and in our development environment - and everything checks out.
Smooth work @benmccallum - tricky nut this one!
So I think this is the issue:
https://github.com/benmccallum/fairybread/blob/76c39cc4f5ca0b792a37f955636449a255ce12a8/src/FairyBread/IRequestExecutorBuilderExtensions.cs#L21-L22
By registering
DefaultValidatorProvider
as singleton and passing insp
as the first argument, you’re passing the root service provider, rather than the service provider that’s for the current http request. When you try and resolve validators insideGetValidators
, they end up being instantiated by the root service provider, which is causing the error you’re seeing (because validators are registered as scoped, but you’re resolving them from a non-scoped service provider).You’ll need to make the
DefaultValidatorProvider
scoped instead, and then I think this should resolve the problem (although I think you may want to split this up into 2 services, as you wouldn’t want the assembly scanning to happen on every request).Note that even with older versions (where validators were Transient) this could’ve still been a problem if a user injected a request scoped service into a transient validator - you’d have ended up with the same issue. Basically, when it comes to dealing with services in aspnet, singleton scope should be avoided for anything that either could have dependencies injected into it, or calls into the service provider directly. (For example, the example in the readme of injecting a dbcontext would be problematic too, assuming the dbcontext is request-scoped)
Hope that helps clarify what’s going on, give me a shout if you need any more info.
Edit: If you want to detect & catch this behaviour inside your integration tests, take a look at what we do when we spin up the web host: https://github.com/FluentValidation/FluentValidation/blob/5c43678a217d5713cde5a0f716e9b46e23c72f21/src/FluentValidation.Tests.AspNetCore/WebAppFixture.cs#L17-L21
Awesome. Thanks for the confirmation, and for the reproduction!
@rune-vikestad I’m encountering the exact same problem in
6.0.1-preview.1
. First time, everything works, but running the mutation a second time causes this error:I’m having issues with
6.0.1-preview.1
after upgrading FairyBread in https://github.com/rune-vikestad/fairybread-dependencyinjection-bugThe
createFoo
mutation returns as expected the first time i run it, but running it a second time yields the following error;