-
-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot resolved scope service ... from root provider #43
Comments
This is the exact same issue I found a few days ago, and talked to Ben on Slack about. As such I've reproduced it in https://github.com/rune-vikestad/fairybread-dependencyinjection-bug |
This one is really weird. I don't really understand it, but it seems like the working profile, FluentValidator correctly registers the valiator and you can see it on the ServiceProvider in it's Services property while debugging. But in the non-working profile, it's not there. |
What's also strange is that when FairyBread crawls the services at startup to create the cache of validators in your DI, it sees the instance there, as it doesn't throw like it would if there were none. |
@JeremySkinner, are you aware of any issues with FluentValidation DI with This is very old, but could it be a regression due to a similar thing? |
TL:DR, somewhere you have a singleton-scoped service that's trying to resolve a request-scoped validator. @benmccallum so the difference in behaviour is because when the environment is set to Looking at the stack trace, it appears that somewhere you have something singleton-scoped that is trying to inject a validator (which is request-scoped as of 10.0). This will cause the validator to implicitly become singleton-scoped too, which is why the service provider is flagging this up. |
So I think this is the issue: fairybread/src/FairyBread/IRequestExecutorBuilderExtensions.cs Lines 21 to 22 in 76c39cc
By registering You'll need to make the 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 |
@JeremySkinner , so glad I tagged you and so very grateful for your help and detailed explanation on this! Will look to resolve this tomorrow everyone. |
Hi all, I've just pushed a There's just one outstanding failing test (which I've currently disabled to get a preview out) which was a test of multiple executions against the Perhaps this isn't a valid scenario. @michaelstaib, should it be possible to call Hmm, perhaps for my tests to be valid now I need to create my own scope that wraps a test... this stuff's tricky :P |
I've fixed the test by resolving the executor x times for x executions, each time in a new scope. But not really sure if that's valid. If I hear back from Michael I can wrap this up and do a proper release. When I get time I'll follow @JeremySkinner 's suggestion about integration testing the different DI behaviour in Development as we've also had issues before with serialization that'd benefit from spitting out JSON via HC's ASP.NET middleware, so I'll take the dive. |
So if you execution on the IRequestExecutor make sure to dispose the results after you have used them. Apart form that you can use it as long as you want .... Except if you are using schema reloads like in schema stitching. In this case we have a proxy class that implements IRequestExecutor which handles all the reload stuff and so on. |
Second, each execution needs a new service scope if you pass in the service provider. If you do not pass in a service provider we will use the main service provider and create a scope internally. |
I'm having issues with The {
"errors": [
{
"message": "Unexpected Execution Error",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"createFoo"
],
"extensions": {
"message": "Cannot access a disposed object.\r\nObject name: 'IServiceProvider'.",
"stackTrace": " at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)\r\n at FairyBread.DefaultValidatorProvider.GetValidators(IMiddlewareContext context, IInputField argument)+MoveNext()\r\n at FairyBread.InputValidationMiddleware.InvokeAsync(IMiddlewareContext context)\r\n at HotChocolate.Utilities.MiddlewareCompiler`1.ExpressionHelper.AwaitTaskHelper(Task task)\r\n at HotChocolate.Execution.Processing.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n at HotChocolate.Execution.Processing.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
}
}
]
} |
@rune-vikestad I'm encountering the exact same problem in {
"errors": [
{
"message": "Unexpected Execution Error",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"sendVerificationSms"
],
"extensions": {
"message": "Cannot access a disposed object.\r\nObject name: 'IServiceProvider'.",
"stackTrace": " at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()\r\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)\r\n at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)\r\n at FairyBread.DefaultValidatorProvider.GetValidators(IMiddlewareContext context, IInputField argument)+MoveNext()\r\n at FairyBread.InputValidationMiddleware.InvokeAsync(IMiddlewareContext context)\r\n at HotChocolate.Utilities.MiddlewareCompiler`1.ExpressionHelper.AwaitTaskHelper(Task task)\r\n at HotChocolate.Execution.Processing.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n at HotChocolate.Execution.Processing.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
}
}
]
} |
@benmccallum Any ideas, Ben? |
Sorry @rune-vikestad and @AradAral , life's a bit hectic my end at the moment (renovating our place while living in it...). I'll try look tonight but if you guys have some time to look too I'd appreciate it. I would've thought that splitting out the crawling of services into IValidatorRegistry which is singleton, from the IValidatorProvider which is now scoped and gets an IServiceProvider injected, would've resolved this. Basically as Jeremy suggested. But I guess for some reason it's passing the same IServiceProvider every time to the IValidatorProvider... so the second time it's used it's disposed... It's similar to how Jeremy does it in FV, here: |
@AradAral @rune-vikestad , had a brainwave thinking it through. Why am I injecting preview.2 on the way, sorry again for the delay! |
Confirmed I can run your repro mutation multiple times too @rune-vikestad and it works. And indeed the unit test now correctly imitates that multi-run scenario, so I'm confident this is fixed. When I get more time I'll add some asp.net core integration tests to spin up a real gql server and implement Jeremy's suggestion to force the DI Development behaviour to get that all checked as well. Raised as #45. |
Kinda need to get this out an unlist the original v6 packages so I'm going to assume this is all OK and close it out. Shout out if there's anything I've missed. Cheers! |
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! |
Awesome. Thanks for the confirmation, and for the reproduction! |
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:
Versions:
The text was updated successfully, but these errors were encountered: