ROUTING in ASP.NET Core | Getting Started With ASP.NET Core Series

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
routing is responsible for matching incoming http request and matching those requests to app's executable endpoints endpoints are units of executable code that handles requests coming to the application endpoints are defined when the application starts and the urls to these endpoints can be generated from the information in them in this video let's learn about the underlying concepts of routing in asp.net core hello everyone if you are new here my name is rahul and welcome back to the youtube channel let's head off to the console and create a new.net web application to understand more about routing let's use the dotnet cli and use the new and the web template to create a new web application this will create an application in the current folder open this up in the ide of your choice in this case i'll use rider the application is loaded up in rider and you can see there is a program.cs file and a startup.cs class all asp.net core templates includes routing in the generated code routing specified in the middleware pipeline in an earlier video we saw more about routing in asp.net core and how to configure that inside the startup.cs class under the configure method is where we define the middleware pipeline here we see that this template already has app.use routing and the app.use endpoints call this is setting up this application with the routes and the endpoints that's required to handle the request use routing adds route matching to the middleware pipeline this middleware looks at the set of endpoints defined in the application and selects the best match based on the request use endpoint method adds endpoint execution code to the middleware pipeline it runs the delegate associated with the selected endpoint by default in this template we can see the use endpoints has one endpoint configured here we use the map get method to handle any request that matches to the root of the request and then calls in to the context of response and writes a hello world let's run the application and see this in action here we are hitting the root of the application and we get back a hello world if we were to pass in any other value it doesn't get matched and we have an http error 404 this is because there is no matching endpoint for this particular request the map get method is defining an endpoint in this application an endpoint is something that can be selected using the url and the http verb the endpoint also has an associated piece of code which is defined as part of this delegate and it writes back into the context.response this is why when this endpoint is getting selected based on the routing it is writing back hello world to the response similar to the map get method we have endpoints.map put the map post map delete etc you can use these methods to map to the appropriate http verb request the route template is used to configure how the endpoint is matched let's see an example let's add a new endpoint to this application so using the endpoints and the map get method we can specify a new route template in here i will say slash hello so this gets matched when the url is to the slash hello endpoint so let's specify the sync context and also specify the delegate handler to simply write back to the context like before let's write back to the context.response and call the right essing method and say hello so this is going to write back hello whenever we come to the slash hello endpoint let's run this and make sure this is working as expected so when it's hitting the root endpoint it gives back the hello world and when i specify slash hello it's going to hit the hello message so this is working as expected now so let's say we want to add a parameter to this particular route in this example let's say we need to add a name so let's specify slash and use the brackets to specify a parameter so this is going to take anything that's after slash hello as the name parameter to retrieve the value of name from the route template let's specify a new variable to our name and use the context the get route value method and call him name so this is going to return back the name from the routes let's use string interpolation and pass back the name with the hello so in this case it's going to specify hello and the name let's run the application again and see if this works as expected so let's specify hello and specify rahul in this example so we get back hello rahul now that we are able to get back the name let's say we want to add a constraint on this route saying this name should only be alphabets so currently i can specify one two three and i'll get back hello one two three so let's add a constraint so that this doesn't work anymore when specifying the route template we can add in constraints using the colon operator let's specify colon and say alpha which represents only alphabets so now if we were to run this application again and go to hello rahul this is going to work as expected so this returns back hello rahul however if i was to specify 123 it says http 404 because there is no matching endpoints for this particular route we have now a constraint for alphabets which is why this is not getting matched even if this was to start with rahul this doesn't get matched because it has integers in this particular name currently specifying a name is mandatory and is not optional so if we were to completely remove the rahul it's again going to throw an http 404 but let's say we don't want this and we want to make this parameter in this template as optional to do that let's add in a question mark in the end of the root template so here we can specify name colon alpha and specify a question mark to say that this is optional if we want to add more constraints let's say this needs to be alphabet and should be of minimum length of at least two characters so we can specify an extra colon and specify minimum length as two so in this case this specifies that the name should be only alphabets it should be having a minimum length of two and is optional so let's run this and check if this is working as expected so now if i go to the hello endpoint it's returning back just the hello because the name is empty now if i specify rahul it works if i specify one two three it returns a 404 because there is no matching route and if i specify just letter r that is also going to fail because it doesn't match the minimum length criteria so i need to specify at least two characters so let's say r and a and that will start matching the name the documentation has the route constrained references so these are the allowed values that you can use inside the curly braces so specifying ind makes that as an int only bool similarly and so on so you can look at the various options that you can specify as a route constraint you can also use regular expressions to add constraints to your route parameters if none of these works for you you can also add a custom constraint let's see how we can do that so let's go back to the source code let's add in a new class my custom constraint so this is going to define a custom constraint to do that i have to implement an interface i route constrained so let's implement that and also implement the missing members so this is going to give us a match method which has a route and the route key and a list of values so let's use that to start writing our constraint so first let's get the value for this particular route so using the route key and the values we can specify the values dot try get value specify which key we are looking for which is also coming from this method so let's specify that and get in the value as out object value so if this value exists inside the values collection let's start adding some constraints so we want the value as a string so let's use value is string and specify that as a string value so this is going to give in the value as a string value if this matches to be a string type if not it will simply go back so if this is a string value all we care about in this case is whether it starts with a 0 or not so let's specify that and return that value so if this particular string route key starts with 0 it is a match but if not it's not so to specify that it fails let's return a blanket false at the end of this method so anytime the route is starting with zero it's going to get matched to specify this as a constraint let's go back to the startup class and first register that inside the configure services method let's use the services and using the add routing method and take in the options that it provides and add the new custom constraint so using the options into the constraint map we can add a new value use a key so let's say my custom which will be used as the route constraint parameter and also specify the type of this particular constraint in this case this is the my custom constraint that we just wrote so this has added the my custom constraint into the routing list let's come down to the configure method and start using this new custom constraint that we have written i already have a new endpoint written so let's use that so this is adding a new endpoint which is slash custom passes in a name which has the constraint my custom added it gets in the name and returns back hello from custom let's run this and verify it's working as expected let's go to the slash custom endpoint and specify a name that starts with 0. so that is working if i was to specify something without starting with 0 this is going to again say http 404. this is because the custom constraint mandates that anything after that which is the name is going to start with a zero so if i say zero and hello this is again going to work and also zero one two three because we don't have any integer constraints on that particular route the routing system as we saw builds on top of the middleware pipeline an asp.net core endpoint is executable which means it has a request delegate that executes when that particular endpoint is matched it's extensible using the metadata collection which we will see in a while it's selectable this is what is being able to select based on the routing information and also it's enumerable which means you can list the collection of endpoints that you have let's see some of this to understand it better to get the current endpoint that's matched for a request you can use the get endpoint method on the context object to see this in action let's add a new middleware between the routing and the endpoints called let's specify a new middleware using the app.use method take in the context and the next middleware in this particular pipeline and then use the context and the getendpoint method this is going to return us the next end point since we don't want to block this pipeline let's call the await and call on to the next since we have an awake we need to make this hole as a sync so let's add in the async here so we have a new middleware which is going to call the get endpoint let's store this to an endpoint variable and we can inspect this while the application is running let's run the application to see how this works the app has started and it has hit the breakpoint so here we are calling on to the http context and the get endpoint method if i was to step over we can get the endpoint values that's currently being selected so that is the route endpoint which specifies that it is on the slash and an http get if we expand this we can see the other information that's associated with that particular endpoint which also has the request delegate the route pattern and other metadata that's associated with it since the route is on a slash it now returns slash so if we leave this and make a call to the slash hello endpoint we are going to see that in there so let's use the slash hello and this is again going to hit the breakpoint so let's step over like before and we can see the end point is now representing the slash hello slash name and the minimum length pattern that we had written this also specifies the request delegate and other information that's associated with it if we were to write the same middleware before the app.use routing method called this endpoint is going to be null because the routing middleware is not yet set up so if you were to put a breakpoint here this is going to be null so let's run this and make sure it is as expected so this hits the first middleware that we wrote so if you were to step over we can see that the endpoint is currently null this is because the routing middleware has not yet been set up for this pipeline so once we go over and hit the next breakpoint you are going to see the endpoint values populated as before so any middleware that's running after the use endpoint call can inspect the endpoint and take appropriate action so let's say for example the map get on the root url we can specify that this endpoint requires authorization using the require authorization method so specifying that is going to add in extra metadata to that particular endpoint so let's remove the first breakpoint because that's anyway is going to be null and run this application it hits the root url and we have the endpoint here so let's step over and inspect that inside the endpoint we can see the route pattern is the slash where we specified the use authorization under the metadata we can now see that there is an authorization attribute getting added so this is used by the authorization middleware to detect if this endpoint requires authorization or not and act accordingly based on the authorization policies that you have set for the application since i have nothing said this is going to throw an exception so this says it contains authorization metadata but a supporting middleware was not found once you set that up this will start working and start authorizing the user who is making this particular request for now since i don't have any specified let's remove the require authorization code url matching is the process by which the routing matches an incoming request to an endpoint it uses the data in the url and the http headers to match the appropriate url this could be extended to use any property inside the request to match the incoming request this first gets all the endpoints that's defined for the application and chooses the best matching url let's see a couple of these examples so here we have a slash hello and a name getting specified here with constraints but if i was to override this and add in a new endpoint let's say map get and specify that as slash hello and given a rahul name so this is going to match this particular as well and this endpoint as well let's make the response a bit more specific so let's say specific match so let's see how this is going to work the application is running so let's specify that particular url in this case hello and rahul so this is going to match the specific endpoint that we wrote for the hello rahul endpoint if this was to be a different name let's say rahul not it's going to call the next endpoint which is generic and has this particular template parameter in here however note that the slash rahul which is more specific took precedence over this endpoint in this case if there are multiple matches for the exact same url then it is going to throw an exception because it cannot choose between them to see that in action let's specify the same url twice so i have two endpoints defined which is slash hello rahul let's run this again and call the slash hello rahul endpoint now you can see that this throws an ambiguous match exception because it has multiple endpoints so let's remove that so that this exception is not thrown anymore the order of how we define these endpoints does not matter on how this gets matched so even if the hello rahul was below this particular endpoint it's going to get matched when that specific url is going to be made there are more rules that goes into how these endpoints are getting matched if you are interested you can take a look at the documentation which will be linked below now that we have seen the basics of the routing and how a routing template is defined and overall how a routing works let's go into specifics and see how this works with controller endpoints this might be the case when you're using an asp.net web api or even maybe an mvc application for this demo i'll just add a controller so let's add in a new folder inside the routing and add a new directory let's call this controllers very similar to how the new template would have created a controller let's add in a new class my test controller to get this to working i need to inherit from controller base let's add in a get method specify a name and return back the string which is string interpolated and specify hello from controller and given the name as well so this is going to return that particular name let's mark this with the api controller attribute and also add in a route which specifies the controller name to specify that let's use the square bracket and specify controller since there is a name let's also add the http get attribute on top of this method and specify a route here which takes in the name value to configure this controller let's go back to the startup under the configure services method we can add in the controllers using the services dot add controllers method so this is going to register the new controller that we just added into the dependency container of asp.net core if you are new to dependency injection in asp.net co check out the video linked here for more details to map this particular controllers inside the use endpoints we can call in the map controllers method to map those controllers that we just added so this is you're going to use a convention and find this particular controller let's run this and see if this works as expected the application is running if we go back to the code the map controllers is using convention to map these controllers into the endpoints so the convention it uses with this particular route specification is that it needs to use all the names in the class without the controller part so in this case this route is going to be my test and we need to pass a name so let's go back and call in to that endpoint so let's say my test and pass in the name rahul so this is returning hello from controller and giving in the name rahul if you don't give the name this is going to give a 404. if we want to make the name optional or add constraints we can do that here as well so like we saw we can say this is going to be alpha and also this is going to be optional so these are going to add the constraint to the name parameter let's run this and see if this is working as expected so let's go to my test and hit rahul endpoint this works as before if i was to specify 123 this is now returning an http 404 this is because it doesn't match the route constraint that we just added even if we remove the parameter since we marked it as optional it now returns back just the hello from controller because the name is empty i hope this helps you to understand more about how routing works in asp.net core what we have seen here is the underlying concepts of how routing works i've also shown how it translates to in example for a controller endpoint we will see more details specific to these applications like web api controller and how you can use routes in a separate video if you like this video please make sure to hit the like button if you want to be notified of future such videos please make sure to subscribe thank you and see you soon
Info
Channel: Rahul Nath
Views: 4,727
Rating: undefined out of 5
Keywords: routing tutorial, routing in asp.net mvc, asp.net core routing controller, asp.net core routing examples, asp.net core routing middleware, asp net core routing optional parameters, asp net core routing parameters, routing in asp.net core, custom constraint in asp.net core routing, asp.net core routing tutorial, asp.net core routing web api, routing fundementals in asp.net core
Id: 3t-As0YBVh0
Channel Id: undefined
Length: 20min 20sec (1220 seconds)
Published: Thu Aug 27 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.