Grpc-dotnet: Is using app.UseMiddleware<IServiceProvidersFeature>() not recommended?

Created on 2 Nov 2020  路  9Comments  路  Source: grpc/grpc-dotnet

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:

  1. Start service
  2. Start client
  3. Perform one successful service call
  4. Restart service
  5. The client using the same gRPC channel now always triggers the following exception:

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?

question

All 9 comments

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?

Was this page helpful?
0 / 5 - 0 ratings