ASP.NET Core Series: Endpoint Routing

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone in this episode of on tonight's show we're gonna learn all about import routing in asp.net core three and three one with our friend Ryan [Music] [Applause] welcome to another episode of the on.net show and so in this episode we're actually going to be doing like a little bit of this series talking about different features about asp.net core 3 and so today I have Ryan who's actually on the asp.net team to talk about some really interesting features that are inside of the framework so Ryan what's going on man like welcome to the show hey so so cool it's good to be here as you mentioned I'm Ryan I work on a spinet core I've been part of the team for a pretty long while now and I work on mostly MVC blazer routing HP client Factory whole bunch of different stuff that we're gonna talk about today cool cool so I know with three oh and you know three one there's tons of new features and you know tons of new capabilities that were enabled but today I really want to talk about endpoint routing like I've seen you do conference talks I've seen YouTube videos and I I'm just like like what is this thing right like what exactly is it how does it work oh why do we even have it right so it'll be really cool you can give us a little bit of an overview about what exactly is endpoint running sure well routing I sort of think of as like the beating heart of the framework like it's at the routings really at the center of everything like before anything else happens in the framework you have to make a decision about where you're going right and that's kind of what routing does for you is like a request comes in where is it going once you figure out where it's going you can do all kinds of other decisions or have all kinds of other functionality based on that so endpoint routing is new in 300 or well it was kind of had a soft opening into - we replaced the implementation of routing with it into - and we kept the API is the same and 300 + 31 which you should be using 31 not 300 are are the sort of like real debut of endpoint routing and you can think of it as like a total rewrite of the mounting system with a couple goals in mind we addressed a bunch of pain points we have dressed a bunch of things that users have been asking for we unified the routing system across a whole bunch of different frameworks so the routing system that's used by MVC is the same as a routing system used by signal are it's the same as G RPC it's the same as blazer on the server all those kinds of things and then performance we put a lot of work into tuning the performance of routing and optimizing it both for scenarios where you have just a few routes as well as scenarios where you have like massive route table so I know before we had like the traditional routing right likes I hats is you you know inside of my configured method inside of my startup I'd have an app dot map MVC or you know map default route or something like that and then we also have attributed a B right so does this does this change any of those or does it replace those things or is this just like an additional option that we have yeah so you should sort of think about endpoint routing is like if you're an MVC user or a web api user you should sort of think about endpoint routing is like an upgrade for the things that you've been doing before you'll find that pretty much everything works the same there's only a couple small things that are different and the kinds of experiences that you're used to in the past will still work the same basically all your friends are there so like if you're used to using map controllers there's a new API that's really similar to map controllers if you're used to using attribute routes literally nothing changes like stuff just works so there's some changes to startup code but other than that we've done a bunch of work to try and keep things working the way that you're familiar with in addition to adding some new things so why don't we look at some code and I want to talk about first some of the problems that we try to solve with endpoint routing and how we do those so let's go to some code okay so I've got a very simple MVC application here and I've got an old startup and a new startup and the reason why I'm showing you this is I'm showing you how we can use the old routes or old routing system and the new routing system and we're going to talk about some of the problems that we solved here so this is an asp net core and I'm using FM BC with MVC options enable endpoint routing false so this is the thing that you must do in 3.0 if you want to continue to use the old routing system and other than that all of this stuff is the same so let me give you let me run this and give you a brief tour of what this application is doing so this will start and I've got asp net core identity here so we've got like a the register the familiar register and login kinds of links here and i've got a home page which you're looking at right now and i've got this like secret page so if i click to this secret page it's going to give me the login screen and the reason why i get the login screen is on my controller I've got the authorized attribute so this is probably something that you've all seen before like it's it's something pretty familiar that we're all used to in a spinner core I can just slap an authorized attribute on a class a controller class or an action method and then I get authorization on that thing which is pretty good and pretty useful the other thing that I've got here is I've got this health checks endpoint health checks is a service or a middleware that you might use in a in a core if you want to expose an endpoint that's for like a monitoring system or some kind of health checking system to like pin your app and see if it's alive and then it's customizable and it's cool but one of the questions that we get a lot from people is like how would I secure this endpoint so I'm gonna go ahead and grab this URL and come here and just prove to you that like okay this is not secured so like anybody who wants to come to this thing what if I wanted somebody who's logged in I want to what if I wanted you to have to be logged in to come to this endpoint well there's really no way to do that in asp net core 2x with the old routing system because things like authentication and and stuff like that are not shared so let's flip over to the new routing system and take a look at how that works and I'm just going to toggle which startup code that I'm using here so we're gonna introduce now some of the endpoint routing startup code and we'll do a little bit of a comparison with the old code so you can ignore this we'll talk about this later and you notice that there's more code here there's more stuff going on and I really want to highlight like this part of the code so we've got use routing which adds a route endpoint routing middleware then inside of there we've got user authentication and use authorization which are my security things use authorization is new by the way and then we've got this use endpoints use endpoints is where you define your endpoints and where you sort of like wire stuff up or map stuff in you can think about use endpoints as being the equivalent to in the past we had use MVC with a delegate so you could think about that as being equivalent to this where you have a place to put all your routes with a route builder this is the this is the endpoint routing way to map a bunch of stuff in so inside of here I've got razor pages wired up because that's doing identity I've got a controller out here from my conventional route for my controller and something different here is I've got health checks I've actually hooked health checks up to routing now instead of health checks being a middleware which is pretty cool and then the other thing that I can do with that is I can say require authorization on that so I can actually up now apply an authorization policy to health checks most of the things that interact with routing now return a builder so there's all kinds of different things that you can attach to something like health checks that's going to apply policies or modify the behavior of that the other cool thing about this is I mentioned that we unified the routing system so along with endpoints you can see that there's a bunch of functionality here for things like doing routing to pages doing raiser pages mapping dynamic routes and then also some of our other frameworks so you can see like Blaser is here so if I were doing blazer server I would have this here and it's part of the same routing system if I were doing signal R I would use map hub I don't have any hubs here so I can't do that and if I were doing G RPC I would say map G RPC service this isn't going to resolve because I don't have the package but you get the idea so we've really turned routing into sort of this hub that like everything can get connected to a cool tidbit about this by the way when James implemented G RPC support for espenak or he didn't implement anything to do with authorization because it's now handled at a higher level we now do authorization via middleware which is this thing so like one of the biggest differences here is authorization used to be a feature that was plugged into MBC or plugged into signal R now it's plugged into routing so everything else that plugs into routing gets to use these features and benefit from them without having to rebuild the functionality that's in MVC or that's in signal R make sense esel yeah it does and I actually have a question about how this has changed how we're doing middleware exactly so one of the first things I see when I'm looking at this file is on line 56 these are used routing and then at Alliance 75 does it use endpoints so I'm guessing you're not line 56 this is routing middleware that's being injected and then between 56 and 75 the stuff that goes in there are things that are our endpoint routing aware yeah right because I'm guessing there's a reason why I use authentication and use authorization come after use routing and not before you know know me yeah there's definitely a reason so we think about this as the area in between here I like to call it like the routing zone is in here anything that's inside here gets to see and react to is to see and react to whatever choices were made by routing and gets to sort of look at the data that was provided by routing and then do things like modify what's going to happen or apply policies like authorization and we'll take a look I have I have a couple slides to talk about sort of how this thing works and then dump into an example and we can look at some of the data in more detail that something like use authorization would use so one of the things that we talked about already is like why would we replace the routing system and we looked at a code sample that demonstrates some of these problems from our point of view maybe not so much from somebody writing the point of view of somebody writing applications on asp net core we frequently talk to people trying to author extensibility or trying to build frameworks or third-party packages on top of asp net core and the same set of comments or the same sort of concerns repeated a lot which were things like hey i'm building a framework like how should i do security how can i integrate with a spinet core security story and the approach that we were using of having security just baked into our frameworks wasn't really scaling up and so the outcome was people either didn't know how to integrate with security if they were building custom functionality or they thought it was too hard and they just sort of built something custom instead which isn't a great experience because you really want something like security to be uniform um the other thing is that we are scaling up the number of frameworks that we're providing and we're building so we're not going to talk much about it in this talk but like we have server-side Blaser now we have G RPC now pace banette core has all this rich functionality and more frameworks and more integration points with different technologies and we wanted to have a good foundation to build those things on top of so that the experience could be consistent and things can be uniform and then the last thing is that we really frequently needed to add more functionality that handles requests and responds to things and middleware or MVC was kind of the only thing that we had for it we really wanted to create something or have the ability to use something that's in between like a middleware and controller doesn't always feel right for like asp net to ship functionality with controllers and us to put controllers in your application so we avoid it so what is endpoint routing fundamentally well it's those two middleware and those two middleware defined what we think of as like a routing zone or an area where middleware can be routing aware and then the sort of separate components of this are we have this new data type called end point and end point is a new primitive that lives on the HTTP context and it represents what was selected by routing so you can think of an endpoint as a piece of data that will tell you here's where this request is going as well as some information about the thing that it's going to then the second piece you have middleware that live inside the routing zone like the authorization middleware and those middleware use metadata rather than that are general purpose rather than civic pieces of like framework specific knowledge like NBC and what's nice about this is that you can have different frameworks that provide different kinds of endpoints and the middleware don't have to change they don't really have to know what's being executed they just look for the metadata that they care about and then the last part is we've defined that zone because we've separated selecting a route from executing the route which allows you to put middleware in between so let's jump back to the code real quick and let's poke around with some endpoints and see if we can understand what they're like so what I've got here is I've expanded that little area that I was hiding from y'all before and I'm gonna run this sample and set a breakpoint in here and we're gonna run under the debugger and then we'll be able to look at some of this data that we're getting in the debugger that's going to tell us about what an endpoint is so this is launching and while this is launching I just want to point out like I've written a middleware that sits in between use routing and use endpoints and this is the kind of thing that you can do if you want to experiment with stuff or you want to see this I think our documentation have a pretty similar sample to this so I've hit this breakpoint and inside of this code I've got the endpoint from the HTTP context now this get endpoint is a new method in 3oh that lives on the HTTP context and it will return the endpoint if you have one and it will return null if you don't have one so I'm in the routing zone and my URL matched so I have an endpoint that's because I went to the URL of the site which is going to match if I had gone to a URL that doesn't match anything I would not have an endpoint here I would have known so if you do write this kind of code be prepared to handle the case where routing didn't match anything the endpoints gonna be gone so right I actually got a question about this part right now that you're talking about so looking at the code right looking at the code very sequentially your middleware is at the top and you actually map your endpoints at the bottom so how is it that middleware that happens before my endpoints knows about the endpoints that have mapped further on in a code that is the million-dollar question the answer is with a lot of trickery so like the real the real answer is that we we started with use routing being the place where you put the end points and use end points with the place that they get executed we also experimented with designs where use end points was optional and you could just leave it out and we I think we previewed maybe three or four different designs of this during the 3.0 previews and we mocked up and played with at least on paper of three or more three or more different designs internally before we even shipped anything to y'all in a preview and the answer is that this is the one that felt the best this is the one that people were at least confused by even though it doesn't reflect reality sometimes sometimes we lie to you trick you we'd like to think that it's for your own good so the truth is that this is the thing that does the routing this thing it when you when you call use routing it puts some state on the app builder and when you call use end points it retrieves that state and then actually adds the end points to it so that's a great question that we we try to be driven by these things of we try to be driven in these decisions by the thing that's going to confuse the least people and is easiest to understand I think it makes sense that people see use end points here and then see the code that's going to get executed like my health checks end point logically execute here in the pipeline it is selected here right so let's take a look at this end point my end point here maps to my MVC controller and you can look at this and you can see that it is a route endpoint so we got some routing information we got this object that's called a route pattern and I think maybe we'll use the we use the inspector window to look at that we got the route pattern and you can see there's all kinds of information over here about the route pattern it's going to basically give us what was the original route that matched that took us to the thing that we're going to and then the endpoint is going to have like a lot more stuff so if we look at the end point the end point has got a display name in this case the display name is like the name of the action method on the controller because that's what we're going to and then the really interesting thing that we've got here is we've got all this metadata and you can sort of think of metadata as like a property bag where everything we know about the thing that's going to be executed goes so because of the fact that this is an MVC controller we've got a controller attribute we've got the controller action filter we've got the save temp data attribute we've got some more filters and some more metadata that are related to MVC and you can see all these types have MVC in the name this one is a really interesting one because this is an MVC action this is actually MVC's action descriptor if you've ever messed with one of those and so all the information that MVC needs to execute this action method has actually been packed into this end point so that MVC can get it back later and can execute it so like you can see we've actually got the method info of the thing that's going to be called we've got the route values that map to this thing we've got controller equals home index equals action the other thing that's kind of cool about this too is now that routing has been integrated at the middleware layer we've actually got a way to get route values from the from the HTTP context so that you can retrieve the route values in a middleware and mess with them that's cool so that that property bag that you're talking about would that include security policies and information like that as well that post can inspect it does it very conveniently does and we can show that in just a second the thing that I wanted to mention about it that's kind of cool is like don't do this but if you want to understand how the authorization middleware works sort of in isolation you can think about the authorization middleware as looking something like this right we want to get an authorization policy and then execute it which is what authorization does we have an endpoint we can go to the metadata and we can say get metadata and I think it's i authorized a ssin I think it's authorization policy or I authorize anyway there's a metadata the name is slipping my mind at the moment but there's a metadata that's associated with authorization that we can actually get from them from the endpoint and then we can come here and we can say okay if policy is not equal to no then do authorization now the actual authorization system is slightly more complex than this but conceptually this is what's happening when we do endpoints let's go ahead and see that in action since you talked about it and I'm just gonna arm out real quick so we're gonna run this again and what I'm gonna do this time is I mentioned to you that I've got my health checks endpoint and my health checks endpoint requires authorization so let's go to that health checks endpoint and then we can see who's let's go to the health checks endpoint and then we can see if we have an authorization policy and we can see what happens because we're not logged in so unbroken the endpoint so you can see I've got this health checks endpoint health checks our endpoints can have a display name so one of the things that map health checks does is it creates an endpoint and assigns it a display name so you can see what it is this display name will appear in things like logs as well to help keep things descriptive so in my metadata I would expect to find an authorized metadata and you can see right here we've got Microsoft a spinet core authorization the authorized attribute so literally the authorized attribute shows up in metadata just like our controller our controller has an authorized attribute on it on that secret endpoint and if I looked at the metadata for that endpoint I would see that authorized attribute here so require authorization literally just takes the authorized attribute and adds it to a collection of metadata now since I'm not logged in I'm just going to hit go here and we'll see what happens so since I'm not logged in the authorization system is going to see that metadata it's going to take action and it's going to redirect me unless I am logged in let's see still turning away here I think we timed out I think that's what happened so yeah so now I've been redirected and you can see that I've been redirected to the account login thing and the metadata is going to be kind of different here you can see that this has got allow anonymous on it because obviously you need to let people that aren't logged in to your login page and you can see that we've got some like razor pages stuff here now instead of just MVC stuff and this is because the login page is implemented with razor pages in identity so you can see we you know in our middleware we observed that we had gone to health checks we saw that we had an authorization metadata and then we saw that the authorization system which runs after us right here kicked us out and redirected us to somewhere else and then we saw where we got redirected to you just from looking at endpoints and metadata so this is a really interesting view about how you could just you know create like this ad-hoc piece of middleware kind of just put it in just like that and it kind of makes me think about in previous versions right before import ratting you know essentially everything was middleware it right like MVC was middleware it was you know app that use MVC and app that you know use static files and use this and use that right and all those were essentially like turned into we're helpful methods that chart in the middleware so now that some of these pieces that have gone into that endpoint routing section at the bottom like what's what exactly is happening there cuz I'm kind of wondering are we are we writing middleware any differently or where things just converted from middleware to endpoints you know like what does this kind of mean for folks that have have written their own frameworks and stuff and want a plug-in to import routing but before they wrote them as middleware and now you know there's a new world that they have to play it yeah so there are two there are two things here so if you're a framework let's say you're some complex framework like signal R or something like that there's a property here called data sources and data sources is really this sort of like it's the type is endpoint data source data sources is really the sort of like power user way to provide endpoints data sources lets you update the collection of endpoints routing support updates as well and lets you do like really powerful stuff where you dynamically add and remove end points or you dynamically define end points so features like map controller out from MVC that define a lot of endpoints or the features in MVC that add your attribute routed controllers definitely use endpoint data sources and use that sort of powerful thing it's a little bit complicated but if you really are writing a framework it's probably where you should start now for something like health checks I can actually write the implementation of this in line there's a pretty simple way to do to do stuff like this and the technical term for this that I came up with is is router wear which is a term that I'm proud of any middleware into router wear so endpoints has got a method on it here I'm trying to think of what it's called the endpoint builder has got a function on it that's that's where it is create application building and this will actually create you a new application builder so like this app right here is an application builder I can get another application builder and create a sub pipeline so I'll call this my my app or I'll call this nested to make it really clear that it's not the same app builder it's a nested app builder so I'll use my nested app builder and I'll stay nested use health checks and I'll pass in Health Z here which is sort of a traditional name that people use for health checks so I've created the nested middleware pipeline I've added the health checks middleware as a middleware to the nested pipeline and then I needed to do something to hook that up to you routing now there's this basic primitive thing here called map and map you can sort of think of as like the most basic way to hook something up to the endpoint builder and the name map was chosen on purpose so like notice that we've got map on the application builder right and map on the application builder takes up a string and a delegate well map on the endpoint builder is meant to be really similar it's a way to fork the pipeline using routing instead of working the pipeline using middleware so I can pass this into my map so I'll say health checks LZ and I actually don't want a URL here I want to just listen on all URLs which I think I think there's a way to do I think there's a way to do it I'm trying to it slipping my mind what it is problems like a slash or something every way yeah let's let's we're not actually going to try this because then it won't fail there's a way to do it if you're curious about the actual implementation of health checks go go take a look at it but we're gonna call map here and then I'm gonna pass in my nested pipeline and then in order to convert an application builder to our request delegate I just call build so it basically makes a function that can be invoked the signature of the quest delegate is the same signature that you get with middle work so I've created a nested application builder pipeline and then I've told routing route requests that go to houses II to this pipeline so this is really similar to the kinds of things that you can do with use so use takes like this is a request delegate or run takes request delegate so we're actually using like the same delegate types for routing as we use with middleware so that these things end up being directly compatible with each other so this is actually really similar to the implementation of map health checks it's just a helper that takes an existing middleware creates a pipeline and then wires it up so you can think about routing as not necessarily a different thing but a new primitive that interacts with some of these existing primitives by the way map we talked about this before does return that builder so if I wanted to I could do things like require authorization on my middleware pipeline nice I think our authorization and I'll set the display name for logging purposes so all those rich sort of features that you would expect from a framework like MVC you can now get with these very bare-bones like sort of primitives right so essentially I could just create a an extension method to that end-points type that'll wrap my middleware to do some of these things so instead of you know all that additional code that you wrote you just write map health checks essentially right and it'll wire up some of that cool stuff for you exactly and then the other dimension of extensibility here is like we think about we think about things that belong in the routing zone as being like it's good for features that want to be routing aware and want to implement cross-cutting concerns or cross-cutting policies so obviously security things come to mind because security features are one of those areas where you tend to want to specialize based on the action method based on the razor page based on the endpoint what is a security behavior of this thing so some other things you might think about that could could be implemented in a routing aware way would be like a rate limiting middleware or a request queuing middleware or even like some of the samples that I put in the documentation are like audit logging like do you want to log every request that goes into a certain endpoint like you could either put that code in your controller or you could implement it in a cross-cutting way and then if you have more usage of it in the feature you can use metadata to tag stuff and have it just sort of work so it gives you another dimension on how to share things and it's not tied to a framework like MVC so if you're using J RPC tomorrow or you're using health checks or you're using some external package that does its own functionality you can write middleware that apply to all those things based on metadata wow this is really cool man this is I feel like I understand this concept way better now than than what I did before so definitely thank you for sharing all this cool information with us do you have any like links or documentation or samples or anything like that that we could pass them to some of our viewers so they can learn a little bit more about how endpoint writing works yeah so the one the main thing that I would want to highlight for anybody the routing documentation for 3/1 and for 300 or might be just for three one is all new so Rick Rick Anderson and I work very hard on this and the routing documentation is all new and has a really good sort of explanation for these kinds of things a lot of what you saw today with samples because there's so much more here than there was really time to talk about in this video so you get some information here about the concepts which we talked about in this video practical examples like a lot of what you've seen here as well as things like guidance for writing a library for writing your own middleware for hooking up middleware to routing as well as things like how to turn up Diagnostics for routing these Doc's were a labor of love and hopefully you find them useful hey thank you again Ryan so much for coming on if folks want to get in contact with you on social media or anything like that like do you have any are you I'm on the socials or anything like that on Twitter the best way to give us feedback and ask questions as always github be shy about asking questions or about giving feedback or just you know something's not clear something's not good we love feedback on github github calm slash net ace peanut core we're now in the dotnet org update your bookmarks you can find me personally on twitter my handle is a very spicy boy I I don't have it written down anywhere but you can find me and Twitter or you can find David Fowler on Twitter and we'd be happy to talk to you also so thank you for coming on and thank everyone here for watching and you had another episode of the on that Nets show we've learned about employ writing from Ryan [Music] you
Info
Channel: dotNET
Views: 13,427
Rating: undefined out of 5
Keywords: .NET, dotnet, .NET COre, dotnet core, dotnetcore, aspnet, asp.net, asp.net core, aspnetcore, Web Dev, Azure, Microsoft, Programming, Software Development, Web Development, Web API, Web Services, Cloud, Docker, Microservices, Docker COmpose
Id: fSSPEM3e7yY
Channel Id: undefined
Length: 32min 49sec (1969 seconds)
Published: Tue Jun 09 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.