A deeper look into the ASP.NET Core Startup class

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there and welcome to the code wrinkles channel for a brand new video this time we'll talk about asp.net core and we'll get started with i would say very simple uh subject but it is still a very i would say underestimated one and we're gonna talk and we'll have a deeper look into the startup.cs class and the reason why i want to do that is that we actually when we get started with asp.net core but even if we are regular dot net developers or dot net core developers we just take everything for granted we have this startup class here and we basically know what it does in a very very basic manner but then when we work on real applications it happens very often that we come across different scenarios where we see that we get errors when we try to register our services or when we try to register our middleware or things very similar to that and this actually comes from a misunderstanding about how actually this startup class is actually designed to work and how different things are registered or configured at different stages and this is why i just want to take a deeper look into what we have here in the startup class to try to understand how exactly this startup class is called when it is called when the methods of the startup class are called and things like that which will help us better understand the anatomy of an asp.net core application so let's get right into it what i have here is a very basic net core 5 or 0.5 api project and this is actually the default template that we get from visual studio when we create a new asp.net square application but i have added only two middleware here that will be reused throughout this video and i have also added a very very simple data cedar service which is actually not a data center it just contains a list of numbers and we have here a method on the service that allows us to add a random number to the list once again the concept of the service or the logic of the service is actually not important here at all what we care about is only what happens here in this startup class so let's get started with it now i want to start by trying to better understand what actually happens when we start a new asp.net core app and here if we go to the program class this is actually the word the very first important part because in the end an msp.net core application is nothing else than a regular console app now as in a regular console app we see that we have this public static void main method which is actually the entry method in our application now if we take a look what happens here is that in this method we actually call this create builder method and then we create we we we run the build method on it and run and what actually what we actually do here is that we create a host for our web application we build that host and then we run that host so we have here three different steps i would say now here this create a host builder create actually in our case a new default builder or uses a default builder and configures a web host so this is the first step the configuration now what this actually means and here we see that we only have this used startup which actually refers to the startup class that we have but actually what happens under the hood is that asp.net core configures the web host with different type of information it gets or it creates a configuration object that is able to read for from our app settings files we can even override this and read different configurations from different files so that we don't have all the configurations in one single file it adds logging to it it creates a service provider where we'll be able to register our services so all these things are happening here under the hood when we uh execute or when the runtime executes this configure web host defaults now during this phase we see that we have here this call as use startup which actually means let's look in the startup class for further configuration of this app and what actually this means is that first of all asp.net the asp.net core runtimes does some magic tricks under the hood and registers different services and configures the host environment and things like that then it passes to our startup class where we can add our custom configurations like services and middleware we'll talk about it just in a few seconds but then probably there are some things that happens under the hood after we use the startup and after everything is created then the host is built and it is run and actually when this the host is run that's actually the moment when our application goes live now why this is important is because when we get here to use the startup we see here that web builders use startup and we specify that we want to use the startup class that we have right here now the idea is i said once again and this is very important before this startup is actually used asp.net core already does configure different things on uh that application builder now what this actually means and this is why we go over to the startup and i would like to take it actually uh from uh from top to bottom is that we have this constructor here and sorry for that so the default template you have in the constructor an eye configuration object and you use it to assign it to this iconfiguration property that you set here now the idea is that in this constructor we could use dependency injection and we can inject services or configurations that are already created or defined by configure web host defaults before this startup is actually used and in fact these methods or this services that that we can inject here in the startup constructors are actually only three one of them is the eye configuration service the other one is the i web host environment let's call it env and the third one is the i host environment now the difference is that in this case the iweb host environment contains environment specific things for a web application while the ihost environment contains environment specific information on a generic host because we could theoretically run asp.net core not only on a web server but we can create our own host where we actually want want to run it but the important thing is and i want to emphasize this in this startup constructor there are only three services that you can inject which is the eye configuration the iweb host environment or the ihost environment these are all the only available services at that point when this constructor for the startup class gets called so we could actually reuse this and we'll use the iweb host environment as we run here this application on a web host because it is a web application let's add also like we have for the configuration we add a public eye web host environment let's call this env al also only with the getter and reset this and the reason why this might actually be useful is because in the iweb host environment you have a lot of different information about your web host and in the configure services method for instance you might want to be able to register different services based on some information that you take from your host so for a very very basic example of this we can say here for instance if env dot is development so only if the environment is a development environment then i want uh services and let's add the scoped one and we'll add our data cedar service okay now the important thing here is that here this service will be added only if we use or if we run this application in a development environment what actually this means it means that if we have an asp.net core variable set to the value of development so only in this case but there are other things of this env that you could actually use for instance you see that uh here you have different type of information which is the webroot pod which is the webroot file provided the content root part the application name now you see that you have a lot of information here and it's very very important because you can actually take this information if needed for instance i don't know if you have a service of which you want to use to write in in the content root so you want to write files there or in the web root you can simply then take this value and pass it to the services actually that uh that you want to register and that actually rely on this type of information so once again this is very very important the first thing in the startup is that in this constructor we can inject three types of services one of them is injected by default in the visual studio template which is the eye configuration service but then we have we can include a web host environment or i host environment and let's go back here to is development and start to also run the application of course nothing will happen in this case because this is only a very very simple registration but what i wanted once again to emphasize is that in the constructor or that or the startup class you can inject only these three services and this is really important because i have seen developers that try to inject here in the constructor services that they actually add here in configure services which is of course not very very fortunate now let's go one step further in our deeper look on into the startup class and then we have actually two methods here we have the configure services method and we have the configure method now these two methods are very important they are both called by the runtime but they are called in a specific order so no matter for instance we could actually take this one for instance let's cut it and we could uh edit at the end so it actually doesn't matter the order in which we actually have these methods declared in the class they always get called by the runtime in the specific order first we get the configure services so this is the first method from the startup class that gets executed and afterwards after the execution of configure services happens then the runtime calls the configure method and as it this is what i wanted to show you is that it's actually not important the order of of the methods in this class actually if you use resharper and you actually use it to to clean up the file it will actually reorder it and the configure method will come before the configure services method even though in the template in the default template the configure services method is before the configure method so once again i just also did this switch manually because i wanted to show you the order of these methods is not important so not the order in which you write them in which you code them but the order in which they are executed or called by the runtime and once again the configure services method gets called first and then the configure method gets called second now let's take those methods one by one in the configure services method we can use it to configure our services so what are services this video won't be a deeper look into services and lifetimes and things like that we on that we will have a totally separate video where we'll treat the concept of dependency injection in asp.net core but just as a common understanding a service is actually a piece of reusable code of or usable components of your application that you want to be able to inject in different parts of your web app for instance you can add a service which calculates of i don't know some taxis for instance and you can inject then the service if you have added it here to this configure services we add it to the dependency injection container so we can inject them automatically in a controller if we need them we can inject them in middleware we can inject them in other services or we can actually inject them also in background workers actually wherever we need to implement that or reuse the type of of functionality we can actually do that so that's the whole point of having or of having this idea of services in asp.net core now services can be registered here very very easily and as an example for that we have already done this registration for the data center now the only thing that i would like to do is to not check the environment for that and i just want to add my service to uh and let's edit its code data cedar once again and that's it now we have added our data cedar service and we can inject it everywhere now i guess that's everything about this configure services method so let's move on to the next step of what happens in the startup class and then last but not least the dotnet runtime calls or invokes this configure method now the configure method is totally different than configure services and the configure method is actually used to configure your middleware pipeline and the middleware pipeline is a very very important concept in asp.net core and i or we have here on this channel i guess three or four different videos on middleware in asp.net core we have a basic overview of what a middleware is what a middleware pipeline is how the requests travel through the middleware pipeline and how the responses travel back through the same middleware pipeline and what we can do there we have also videos on creating a custom middleware so if if you want to get a deeper look into what middleware is then please refer to those videos i will leave a link to those videos in the description of this one so you might be able to check them out later if you want now the idea here is that uh when we configure middleware it's actually very very important the order in which we actually uh configure this type of middleware because actually as outlined in the other videos once the request comes in it travels through all the middleware actually in the order of registration and this is why it is very very important but another important thing and this is actually what i want to emphasize more in the configure method in this video is that as you have already configured your services this means that in if you need some services in the configure method you can easily inject the services uh via this method so it's actually very very easy the only thing that we have to do is just provide here for instance i want to inject i and i logger factory and i want to eject to inject my data cedar okay so what i can do here is then simply reuse these services in the configure method for instance let's create a var uh logger which would be loggerfactory.createlogger and we have to specify the category name for the logger configure middleware so this is actually where our logger uh is used now if we have a logger for instance we can for we can log here logger.log information environment is development specific middleware will be registered this is what we log here but then we can also add a log here so logger.log information and here we can say for instance that uh registering https redirection middleware and i guess you get the idea the same way we could for instance go here and log things i guess the important part here is that we can simply in this configure method we can inject the services that we have registered uh previously in the configure services method and this is useful for instance because if you register a db context you could inject it here and actually do some database cleanup or data seeding or things similar to that let's also add registering our routing the same way we could use our own custom service that uh that we have created or that we want or that we have injected here in this configure method we have here data cedar equals uh cedar i guess we already have the cedar seeder so we can just um consider dots let's call this add random number which will add a random number and then we can use the logger once again log information and here we can log the last number that was added last number added and we can see here it is the leader dot numbers dot last and then uh tostring make sure that we call it correctly okay so right now we will see that if you run the application uh we'll be able to see a different type of logs here so it's all the logging that we have added in the configure method okay so we can see here that we have here the last number added which was 89 then we see that environment is development specific middleweight will be registered then registering https redirection middleware then registering routing so all the logs that we have written here we can see in the console and this is all only possible because here in this configure method we can actually inject the services that we need and that were previously configured in this configure services method and this is the reason why i guess now you get a better understanding why the configure services method gets called first and why the configure method gets called second because here in this method we just want to use services that we register here and this is a very very important concept now here i just want to go to another very very important topic in the way that you could customize actually your startup class and the way that you register services or middleware is that you can use an iconfiguration filter interface to configure actually middleware in the configure services method now the reason why you would like to do that actually is a very very simple one and the the main idea of that is that you actually for instance especially if you create maybe a class library that you will i don't know make available when you get packaged ideally consumers should only i don't know maybe make a call to add your service and then the service should actually add all the dependency that it needs which means all other services but it also should add some middleware to the middleware pipeline so the idea is that let's let's go one by one we have here two middleware of course we have this author header middleware which adds a new header to the response and logs the information and we have here the order header middleware which adds a new header which is called order and it just generates a random number so the way we could do this for instance if we go here after we log everything but before environment is development we can say here app.uh and both of those middleware have also extension methods and here i can say app i use author header middleware and we can say app.use order header middleware and actually what happens is that will add all these to middleware to our pipeline and if we run the application and look just a little bit in the console we can see here that uh well what it happens uh adding order header to the response either order header to the response and since the browser opened the swagger documentation for this api which calls actually two times then we get this information two different types now the idea is that if we see here also is the order so first we have the author header and then we have the order header and this is because this is the exact this is exactly the order in which we have registered these two middleware now let's assume for one second that i have a class library that is designed to handle orders and what i want to do is i want to provide consumers the option to actually only use a single method registration maybe in configure services but i also want to add some middleware to the pipeline and also what i want is that i would like to add some middleware that gets executed before all other middleware here in the pipeline so in this case in this scenario we can use this very nice feature that we have in asp.net core which is an i startup filter now let's try to add this here in our services so let's add a new class and this uh class let's call it order uh header or top filter and we just have to implement i start up filter i guess we have to add the using for that which would be no problem and if we implement the interface it's actually everything that we need and you see that in this implementation of the interface we just get this configure method that takes in an application builder so exactly what we get in the configure method here and it returns that same application builder and then it will be passed actually here so what it means is that we will get the application builder in our services we will add our middleware to it and then when the configure method is called that i application builder will be passed to the configure method with our middleware already registered so this is the whole logic of uh of this type of configuration so let's also add some some things here so what i would like to do here is um i would just want to return um the builder because you see that we uh we returned an action of i application builder so in that builder we can say uh builder dot use middleware and we can specify it i would like to use the order header middleware and uh that should do it of course i need to add the necessary usings and that should be it now if i have this eye startup builder a filter what i can do here is i can go back to the startup and i can say here for instance services and i can add this as transient and i say that i want to add a service which is of type i startup filter and the implementation is the order header startup filter okay so we have added this to the configure services now we can remove the order here and we see that use author header is actually at the same place so once again what i would expect to happen here is that when the configure services method gets called which gets called before the configure method here for this one for for this service of type i startup filter i actually get here an i application builder to which i am able to add my middleware once again from the configure services uh this happens everything in the configure services method so i am able to use the middleware and then when the runtime calls the configure method as it happens here what it will be it will pass the eye application builder that i have already configured with my middleware in this startup filter and this is why i would expect that right now i would see the logging from the order middleware before the logging from the use author header middleware so let's run this application once again and check exactly out what will happen okay so we had an error here i guess but uh yeah we had an error sorry for that that is very very unfortunate uh because i guess the error was let me go here to the order uh okay of course what um what happens here here is that of course we have to invoke the next sorry for that because it's regular to what happens in a normal middleware here i am able to call the next and i pass in the builder and that should do it so yeah this is the reason why i actually have short-circuited the entire middleware pipeline because i haven't used this uh next delegate so basically everything stopped here so the request or the the pipeline was not configured further everything stopped here because i didn't use this next this is why it is important to use this next delegate also in um in startup filters but also of course when you write your custom middleware now let's run the application again and once again when this gets called here we see that in this time we add the order is the first one that gets executed and the author header is the second one that's that gets executed and once again this is only because i have decided to use this i start off filter and i can use this istartup filter to register middleware to to the pipeline before any other middleware in this configure method is registered which actually could be very very nice for instance if you uh if you develop a class library that you make available through a new get package you might for instance create an extension method uh services uh add my service and in that extension method you would actually add for instance your data cedar but you would also add the startup filters and therefore configure or add middleware to the pipeline that is specific to your library and in fact this is actually a technique that is used by most of uh of the different libraries that are used in asp.net core like logging libraries and so on because everything or almost everything also needs some custom middleware to it and in order to avoid the necessity to add a service and then separately add and configure different type of middleware they just supply one method and use startup filters to actually add all the middleware that they need to that pipeline good i guess uh that should be it for this video we covered all the logic that we have actually in the startup file we try to understand how the startup of an asp.net query application works starting from the program class then we have explained what we can actually inject in the constructor of the startup class and then we have talked about the difference of the configure services method and the configure method and why it is really important to know or to be aware about the order in which these two methods are called by the dotnet runtime because this allows us the option actually to inject in the configure method actually all the services that we need and that we have also previously configured or added here to the dependency injection container and we have done this by having the logger as an example and our custom seeder also as an example and we use the logger done just to look different type of information here in this configure method and then last but not least uh we have looked into why what an eye startup filter is and we have discussed about the scenario this scenario in which using a startup filter might be useful this being said thank you very much for watching if you did enjoy this content and you find it useful please don't be shy and share it with your peers on your social networks wherever you want and also a thumbs up and to subscribe would be very very much appreciated thank you once again very much for watching and until the next time i wish you the very best
Info
Channel: Codewrinkles
Views: 1,893
Rating: 5 out of 5
Keywords: ASP.NET Core, ASPNEtCore, .NET, .NET Core, Services, Middleware, Startup, Programming, Web Development
Id: -zjscjCovPo
Channel Id: undefined
Length: 32min 48sec (1968 seconds)
Published: Thu Apr 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.