Hi team,
I found sample code on the gRPC project about not allocating request scopes:
https://github.com/grpc/grpc-dotnet/blob/master/perf/benchmarkapps/GrpcAspNetCoreServer/Startup.cs
The class of interest is ServiceProvidersMiddleware.
The way i get my application to perpetually error is to:
Connection id ""0HM3V8CGMTP5C"", Request id ""0HM3V8CGMTP5C:00000003"": An unhandled exception was thrown by the application.
System.ObjectDisposedException: IFeatureCollection has been disposed.
Object name: 'Collection'.
at Microsoft.AspNetCore.Http.Features.FeatureReferences1.ThrowContextDisposed()
at Microsoft.AspNetCore.Http.Features.FeatureReferences1.ContextDisposed()
at Microsoft.AspNetCore.Http.Features.FeatureReferences1.Fetch[TFeature](TFeature& cached, Func2 factory)
at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler1.ChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 application)
Can you please confirm if this error is to be expected if one uses an IServiceProvidersFeature implemenation to avoid creating the request scope?
That sample is a just bad implementation. I assume it existed purely for measuring a very specific use case but it's broken as it doesn't actually create a scoped container
@davidfowl Super quick reply! Would you be able to point me at a proper implementation, or point out the boilerplate required to actually use this with the goal of avoiding allocating request scopes?
That's code from a benchmark that is designed to avoid creating a scoped DI collection. You're using APIs that requires a scoped collection.
Just don't use it in your app.
@MaximGurschi why are you trying to avoid creating request scopes? @JamesNK I'm not sure that's possible.
Its definitely possible. The middleware prevents a scope being created per-request and makes HttpContext.RequestServices return the app IServiceProvider instead.
That will break anything in the framework that tries to resolve a scoped service and any disposal transient object will leak
@davidfowl I assumed that was an easy win to avoid one more allocation within the service. I discovered the code in the samples and decided to apply it thinking it was correct. But then i was getting the error i described. Would be nice to know definitively if this is not allowed to use or what are the constraints i am supposed to follow in order to use it. My endpoints are of the unary and bidi flavour and all require "[AuthorizeAttribute]". I don't know about "scoped collections" but i believe i don't do anything else special.
I would stay away from trying to do this as it breaks too many assumptions about scoped (and sometimes transient) services
Thank you. I have removed that - even if possible to get it to work there is clearly more to it. On a side note - can you please confirm if a GrpcChannel object is meant survive long backend downtimes? I've tested creating a channel with no active backend service, called a method on the service - that failed as expected and then after a 5 more minutes of downtime, once i brought the service back online, i see the client GrpcChannel still works and i can make calls. Can you please confirm if i can rely on this?