The first time I have encountered this problem was during EF Core migration. If you assume that the httpcontext exists and a service constructor uses the context then the constructor fails and the EF Core tools remain stuck without giving any errors. Troubleshooting this issue was a very valuable lesson.
So it's safe to use IHttpContextAccessor in a within a controller logic since the HTTP context is still active and be careful when using it with custom services which are not related to the HTTP context itself?
AService issue can happen with any service registered as scoped if the work done inside AService is "background work" (not awaited) done by those scoped services. Request is finished before the work (because work is not awaited), and services registered as scoped are disposed in the middle of the work. Kaboom Solution is not to await but to have another scope for background work initiated from http request.
@@unskeptable No, scope is disposed when http request is finished, and http request does not wait for "background job. So if you dont await a Task (whatever it is), and its execution last longer than execution of request (scope), if task dependencies are registered as scoped, task will fail, because dependencies are destroyed. Solution is to create new Scope manualy for background stuff, and that will create diferent instances of registered dependencies.
I didn't get the point why we missed HttpContext after await Task.Delay(). Since it's stored as AsyncLocal it should be there when continuation thread is perfoming further action. Or with thread continuation there will be a different context where HttpContext is not set?
as the httpcontext is retained in the service, the execution continues we've seen in the DefaultHttpContext at Kestrel level that is where HttpContext is cleared from HttpContextAccessor delay finishes and HttpContext is no longer there null pointer exception
The main takeaway for me is that the backend logic should NOT be dependent on the application framework (e.g. ASP or WCF etc). So I did not push through with the use of HttpContextAccessor to migrate a WCF backend service that depends on the WCF HTTPContext
Great video! So if I have a flow which follows this pattern: 1. Controller action is hit 2. Controller constructs and sends a command with MediatR 3. Inside the command handlers we have an ICurrentUserService which uses IHttpContextAccessor Then we could run into problems? (If so is there any way to avoid having to pass the user information into each command in the controller?)
If ICurrentUserService is a scoped service you can preload it in the middleware after authentication middleware. Dependency Injection is really bad for this - if you let this image in your mind sink in - you can’t see all the object coming to fulfill your handler. So you end up with ICurrentUser interfaces which have to be prepared. In your case it’s not prepared but implemented with Ihttpcontext, if you want to reuse a service somewhere else you’ll have to supply different implementation; now you have 2 services behind same interface, which one do you inject? Well now you have to inject Ienumerable and pick by type and hopefully you can see how shit this is. Preparing is a bit cleaner when your using DI, ideally you want to do this without DI at handler level where you prepare everything, but MediatR is shit since it promises portability but really destroys the point of transition between server to BL.
@@RawCoding I see, so does preloading mean we can inject it into a custom middleware after Authentication, set the properties needed from the HTTPContext, and then have those values available to other services? (Essentially breaking the dependency on IHTTPContextAccessor)?
Actually further to this, (apologies if there is an obvious answer), doesn't preloading this service in middleware imply we have some sort of Setter on the User Service to set the current user properties? And if so doesn't that mean that all downstream services will also be able to overwrite it?
You might have missed the point, you’re thinking surface level (how do I use a service) rather than deeper understanding (how does the service works) To answer your question directly: just use httpcontext in mapget no need for accessor
Don’t think it’s anyone’s fault, kinda like you have to think about race conditions and deadlock in asynchronous operations, you gotta do the same here but make sure that your services won’t be used outside of HttpContext
What? If you kick off 2 tasks in parallel that share a resource you have to think about concurrency problems, it’s just what happens. Nothing to do with awaiting or c# or hangfire. The point is that with httpcontextaccessor it forces you to think about these problems With hangfire you’ll have to think about different problems Some are essential some are accidental, in the case of the accessor the problem is accidental
We are waiting for that *AsyncLocal* dedicated video :)
Thank you Anton.
The first time I have encountered this problem was during EF Core migration. If you assume that the httpcontext exists and a service constructor uses the context then the constructor fails and the EF Core tools remain stuck without giving any errors. Troubleshooting this issue was a very valuable lesson.
Wow just heard that you will visit one of our offices with a presentation, too bad I work in other office. Thank you for sharing knowledge
I’ll see if it can be a live cal or something like that
So it's safe to use IHttpContextAccessor in a within a controller logic since the HTTP context is still active and be careful when using it with custom services which are not related to the HTTP context itself?
AService issue can happen with any service registered as scoped if the work done inside AService is "background work" (not awaited) done by those scoped services.
Request is finished before the work (because work is not awaited), and services registered as scoped are disposed in the middle of the work. Kaboom
Solution is not to await but to have another scope for background work initiated from http request.
When is the new scope disposed ? Does it get automatically disposed after the background job is finished ?
@@unskeptable No, scope is disposed when http request is finished, and http request does not wait for "background job. So if you dont await a Task (whatever it is), and its execution last longer than execution of request (scope), if task dependencies are registered as scoped, task will fail, because dependencies are destroyed.
Solution is to create new Scope manualy for background stuff, and that will create diferent instances of registered dependencies.
One day I saw IHttpContextAccessor smoking by the bike rack, and I never used it since.
I didn't get the point why we missed HttpContext after await Task.Delay(). Since it's stored as AsyncLocal it should be there when continuation thread is perfoming further action. Or with thread continuation there will be a different context where HttpContext is not set?
as the httpcontext is retained in the service, the execution continues
we've seen in the DefaultHttpContext at Kestrel level that is where HttpContext is cleared from HttpContextAccessor
delay finishes and HttpContext is no longer there
null pointer exception
The main takeaway for me is that the backend logic should NOT be dependent on the application framework (e.g. ASP or WCF etc).
So I did not push through with the use of HttpContextAccessor to migrate a WCF backend service that depends on the WCF HTTPContext
That was excellent. Very clear!
Take a shot each time "HTTP context accessor" is said, RIP 😂
😂
you're the anthonywrites code of C#
Great video!
So if I have a flow which follows this pattern:
1. Controller action is hit
2. Controller constructs and sends a command with MediatR
3. Inside the command handlers we have an ICurrentUserService which uses IHttpContextAccessor
Then we could run into problems? (If so is there any way to avoid having to pass the user information into each command in the controller?)
This was going to be my question as well
If ICurrentUserService is a scoped service you can preload it in the middleware after authentication middleware.
Dependency Injection is really bad for this - if you let this image in your mind sink in - you can’t see all the object coming to fulfill your handler. So you end up with ICurrentUser interfaces which have to be prepared. In your case it’s not prepared but implemented with Ihttpcontext, if you want to reuse a service somewhere else you’ll have to supply different implementation; now you have 2 services behind same interface, which one do you inject? Well now you have to inject Ienumerable and pick by type and hopefully you can see how shit this is.
Preparing is a bit cleaner when your using DI, ideally you want to do this without DI at handler level where you prepare everything, but MediatR is shit since it promises portability but really destroys the point of transition between server to BL.
@@RawCoding I see, so does preloading mean we can inject it into a custom middleware after Authentication, set the properties needed from the HTTPContext, and then have those values available to other services? (Essentially breaking the dependency on IHTTPContextAccessor)?
@@nathanbrown2387 and that service will be scoped or transite by default.
Actually further to this, (apologies if there is an obvious answer), doesn't preloading this service in middleware imply we have some sort of Setter on the User Service to set the current user properties? And if so doesn't that mean that all downstream services will also be able to overwrite it?
I think he is talking about httpcontextaccessor. But not sure
So the fix is to inject the accessor into mapgets lambdas ?
You might have missed the point, you’re thinking surface level (how do I use a service) rather than deeper understanding (how does the service works)
To answer your question directly: just use httpcontext in mapget no need for accessor
Nice video
Hopefully ur c# has advanced topics as well
Nice video, I've come across this issue, indeed
Is there the httpcontextaccessors fault or your fault for not awaiting?...
Don’t think it’s anyone’s fault, kinda like you have to think about race conditions and deadlock in asynchronous operations, you gotta do the same here but make sure that your services won’t be used outside of HttpContext
@@RawCoding I'm faily sure it bad practice to not await a task, When you need fire and forget use something like hangfire instead?
What? If you kick off 2 tasks in parallel that share a resource you have to think about concurrency problems, it’s just what happens. Nothing to do with awaiting or c# or hangfire.
The point is that with httpcontextaccessor it forces you to think about these problems
With hangfire you’ll have to think about different problems
Some are essential some are accidental, in the case of the accessor the problem is accidental
Auth god
I didn't understand anything :) :_(