Dangers of using IHttpContextAccessor

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to the recording YouTube channel my name is Anton and today we're going to be talking about the ihttp context accessor what kind of problems you can run into it how to avoid these problems we're going to be taking a look at some under the hood stuff of how does it work how does the HTTP context appear in there Etc basically trying to become better Engineers with better awareness of the tools that we're using don't forget if you're enjoying the video leave a like subscribe make sure to check out the description I have a c-sharp course out if you want to know c-sharp as I do it I highly recommend you go ahead and check it out with that let's go ahead and get started here we have the sample application with a couple of files nothing too extreme we have the program CS file and mainly we have three endpoints and this root endpoint is to outline the current user that is signed in the user that is signed in I am mocking an authentication schema with this always authenticated authentication Handler if you don't understand about authentication you you're in luck I have quite a few episodes on it go ahead and check out the description basically all this means is that we're always going to be signed in as this user you don't need to call login or anything like that amongst other services we're adding the add HTTP context accessor and then we're registering a Singleton service some kind of business logic and then a background notification service which is going to be a hosted service so it's something that is running in the background if I open up the terminal the application is already running and if we just take a look at the route we have this test user with the test email coming back to the code we're going to take a look at the first endpoint and this a service which is registered as a Singleton and it has a function that is something slow async now this example is copied from this Outline by debit Fowler which explains why this service is bad but I don't think this example actually illustrates the point of how you can run it into this issue blindly so that's what we're going to be learning about today nevertheless first of all let's observe the issue this function is going to be a fire and forget task which we're gonna wait for a little bit and then we're gonna try to access the HTTP context and we access it by hitting the dummy endpoint and we kick off a task here coming back over here let's go ahead and kick off a dummy we have okay we come back if we take a look at the console nothing is being printed it is failing silently we don't actually see anything if we open this up and I will uncomment this and I will actually output something to the logger so we can actually see this failing the application will restart I'll come back over here I'll refresh and then coming back over here we see the explosion happening the reason the explosion is happening is the HTTP context inside the HTTP context accessor is null and that is the exception that we're getting here the reason it is null is because the HTTP context represents the HTTP context I don't know how else to say it other than when the request starts that's when the HTTP context has created and when the request ends that's when the HTTP context is disposed of we will take a look at the code where that actually happens before we do the Deep diving we're gonna take a look at some code that you might write in the future that will essentially make you encounter this issue so here is some kind of service it is a class with a function some server get injected into here and what we're trying to do is do something with the user at this point we're notifying the user but it can be literally anything the point is you're trying to access the user the user exists on the HTTP context and the MVC world the claims principle wasn't actually injectable so the only way that you can get the user is through the HTTP context so you would have your business logic rely on the ihttp context accessor and you would attempt to do something like this if we come back to program CS we will have the notify service over here we have the business logic and we notify the user now because we're awaiting over here everything is going to run smoothly and that is basically the experience that you would have so let's open up the terminal stuff is going to get restarted let's go ahead and notify everything is going to be okay and notification is successful sometime is going to pass and what you actually want to have is a background service that is going to pull the database check some State and then if that states meet some kind of rules it is going to try to notify the user so you set up your background service you register it as a hosted service and then as you're getting a signal to notify the user again this can be a query to the database in the loop all I'm doing here is passing a message down a channel I'm then creating a scope and then I'm retrieving the business logic because that logic of notifying a user I want that to be reusable and then I notify the user if I go to program CS we have the background notification service over here and I write test into the background notification service so that's going to go into this channel right over here and then this channel reader is going to pick up the message okay so that's basically how it's going to go into here with this example it's a little bit more of a realistic example of what is being highlighted over here you start off with logic that was running during an HTTP request and then you want to execute that same logic outside of an HTTP request and that is how you essentially encounter this issue so notify Dash BS if I open up we will see that we again encounter the no reference exception on the ihttp context accessor at this point if you are still listening the audience is pretty much split into two parts the first one that has been taught the lesson or has encountered this issue and learned the lesson or the second part that is maybe a little bit blind first time you hear about this ihttp context accessor what do you need to understand to not encounter this issue and similar issues there will be three things first is the concept of the HTTP server and that is the asp.net core application that you're programming second is the business logic this business logic should be able to exist outside of the asp.net core server generally what happens is you take the business logic and you register it with the dependency injection container and then that business logic will get injected into your MVC controllers or endpoints and at that point everything seems to be fused together you you need to understand that your business logic that is even though it is injected through the dependency injection controller should not rely on services that are built for the asp.net core framework the ihttp context accessor is an example of a service which is used for the asp.net core framework to do HTTP web server things as you receive the request it's going to go through the middleware pipeline and at that point you need to extract all the information that you can get you're essentially preparing the scene and then you're injecting it all into the business logic and you're setting up your business logic to then execute so you still have your web server you still have your business logic controllers and endpoints is that place where you transfer from the web server world into your business logic World As Long as You Follow that rule you will never encounter an issue like this where you will spot this belongs to the web server because there is some awareness of http RPC websockets whatever other web services notion there might be you want to take that out let's come back to the code and actually inspect what is the ihttp context accessor and how is it set so first of all let's unpackage add HTTP context accessor and here we will see the HTTP context accessor being registered and it's actually registered as a Singleton service so even though it exists only for the scope of the HTTP request it itself is not a scoped service the thing that actually gives the ihttp context access its scopeness is this async local which is a pretty loaded concept and in order to understand how it actually works under the hood deserves a video of its own looking at this all you need to understand is asynclocal is the thing that will make the the HTTP context holder the thing that holds the HTTP context for this specific request that is being made to the server because that request will be executed in an async task asynclocal is the thing which is going to scope this HTTP context to the task or to the async context which is going to be processing the request with that let's back out back into program Cs and we're going to understand at which point the HTTP context is actually placed into the ihttp context accessor what I'm about to do here you can get more information from the Kestrel video I did where we try to understand if it's worth building our own web framework on top of kestrel similar to asp.net core the answer to which is no but nevertheless we learn things about Kestrel and how to interact with Kestrel here I'm just going to show you how to walk down to Kestrel from your asp.net core application let's go ahead and decompile run and here we'll have this hosting abstractions host extensions run and here again down to run async here is where the web server Starts Here It basically just waits for the web server to shut down so until you actually shut down the server the execution is going to be paused here we're going to go in to start a sync and this is on the interface so we want to go to the implementation of the host class and here we will go through execution up until we reach a loop where we have a bunch of hosted Services if we come back to program CS where I register the background notification service which is a background service which is still a hosted service the Kestrel server is a background service which is running in the background and servicing your requests coming back to the host we have the hosted Services over here and start async as being called specifically the Kestrel web server is a generic web host server and here again we will scroll down up until we have this application which is essentially the request delegate if you know what the request delegate your web server your asp.net core app is essentially just a configured middleware pipeline which will get passed down into this hosting application the start async over here is called on the server so I server or implementations for I server will be the Kestrel server and Castro server internal implementation and then you can also have an is HTTP server okay we are particularly interested or not so interested in the actual classes but rather the thing that is passed down to the Kestrel server so coming back over here we have start async and HTTP application is being passed down into it we're gonna go into host application and down here we will first have a create context we will then have process request async and then dispose of context to summarize these three functions the create context is when you are receiving the request so you are doing some setup you're then processing the request and that's going to be the underscore application which is again just your middleware pipeline and then you have the dispose context which is basically going to tear everything down in these contexts what is being used is a default HTTP context which is a service which is registered at the point of this create Builder so when you initially set up your Builder this service already exists internally and I've gone to bad Services over here but I want to be over here okay and sorry I wasn't talking about the default HTTP context is the default HTTP context Factory this is a service which exists from the beginning over here when you call create Builder okay the default HTTP context Factory if we take a look at the create function that is going to be inside the default HTTP context factoring so just this class when we create the HTTP context so the default HTTP context over here it goes through an initialization process the default HTTP context Factory because it comes from the same dependency injection container where you're registering your services it is attempting to extract an ihttp context accessor from that same container you can see that this HTTP context accessor if you never call add a HTTP context accessor it is actually going to be no so this logic has to account for that fact if the service is present this is actually just gonna go ahead and set the HTTP context on the HTTP context accessor okay so this answers the question of when does the HTTP context actually gets placed into the HTTP context accessor and how long the does it actually exist there if we again come back to the host application during the setup of the request the ihdp context accessor service actually gets prepared and loaded with the created HTTP context over here you then place the HTTP context into the middleware pipeline so it gets processed and after which if we have the HTTP context accessor we clear it from the context and the dispose on the HTTP context Factory this is where it's actually going to clear it away from the HTTP context accessor itself now I've probably said HTTP context accessor like a gazillion times but all you need to know is that HTTP context accessor is set up and the HTTP context inside the HTTP context accessor gets wiped out before and after the HTTP context actually gets sent into your middleware with that I think it's a good time to end the video remember even though your business logic sits inside the web server you want to program it as if it doesn't know anything about the web server this way you're never going to encounter a problem like relying on the ihttp context accessor to get a user or some kind of other state from the HTTP request make sure all of that information is extracted before or at the point of you entering your endpoint or action or Handler on the controller razor page whatever it is that endpoint action or Handler is the transition from the HTTP server world into your business logic as always if you enjoyed the video don't forget to leave a like subscribe if you have any questions make sure to leave them in the comments section go join my Discord server and if you want the code for this video as well as my other videos come support me on patreon I will really appreciate it and a very very big thank you to all of my current patreon supporters you helped me make these videos don't forget to check out my c-sharp course again thank you for watching have a good day
Info
Channel: Raw Coding
Views: 9,574
Rating: undefined out of 5
Keywords: asp.net core, c#, IHttpContextAccessor, tutorial, explained, guide, HttpContext
Id: yR7AwCh8KFc
Channel Id: undefined
Length: 15min 44sec (944 seconds)
Published: Wed Mar 22 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.