ASP.NET Community Standup - Simplifying web apps with new minimal APIs in ASP.NET Core 6

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Music] do [Music] [Music] [Applause] [Music] and hello welcome to the asp.net community stand-up and today we have my name is john galloway i'm a pm on the.net community team welcoming back damien edwards welcome dave hi hello and stephen halter hi and i go by stefan so damn it yeah okay well i almost put like the pronunciation guide in the uh in the little icon at the bottom john's gonna add to his presenter notes now before we start right we'll always all right well and and so stephanie you've been working on a lot of cool stuff or we're chatting before this you've worked on uh signalr and kestrel and then lately you've been working on these minimal apis yeah so i'm super excited um damian's got a playground that he's uh ready to share showing off uh this new host and this new way of defining endpoints in asp.net so awesome okay well hi well we will so it's always fun to see people joining from all around the world so cool um we will start as we do with the community links i've just shared them out in the chat i will have them on a banner um all right let's do this so here we go uh starting with uh this is a nice one um so marinko talking about middleware and i like just kind of the the flow kind of going through and explaining what you know what is middleware how does it work uh building up and talking about and this one kind of focuses a little more on the conditional middleware approach so showing you know here's the standard middleware you get here's how to create some middleware um then as we go through showing the use method so the kind of simplest case and then uh showing this whole kind of idea of using map and map win for branching so you know cases where you've got multiple things going on and and uh in this case first showing just uh with use run both mapped and then showing the case where you want to do map when and you know routing that to a specific query so uh then of course things get cluttered as you keep adding more and more in and so it's time to move things to different files and then showing uh pulling those in from a factory so this is just kind of a nice uh if you've used middleware in the past and haven't you know kind of looked at how to build your own middleware or how to kind of hook it all together this is kind of a nice walkthrough there it's good to get back to the basics sometimes and really nail exactly those things yeah and you know i i i try to balance it not you know cover we could have ones on middleware every other week or something yeah i like this kind of building up from the basics and we forget you know that there are people that are coming new to asp.net core all the time and you know it's an important concept to get so right all right uh speaking of kind of the learning you know learning things new and figuring out where to go uh so moyan has been updating this roadmap over time and this is just really cool this is a uh you know what are the different skills where do you get started what do you learn next that sort of thing so of course it's opinionated but that's that's great that's the idea here is just kind of like figuring out here's where you get started and what to learn next so all sorts of different um you know patterns and libraries and things like that and of course keep learning when you get done and then a bunch of resources afterwards so very good stuff uh this is neat just looking at minimal apis so dodgy has a a repo practical practical asp.net core and these are always things where he's updating constantly updating these they're very lightweight patterns and so very simple focused targeted scenarios so here he's updated uh one and this is a single oops this is a single file and just updating this to um you know to build using the minimal apis so uh i wanted to share this first of all just this is topical to what we're talking about but just a reminder to people this practical asp.net core has been updated for years and all these very targeted scenarios so as you're as you're learning concepts these are helpful and then it's also to see how you know for instance i don't know if we'll just pick a random one and then i'll go with you know say this this one here and you can see in the history where these just keep getting updated well of course i pick one that's only better for a few but he continually updates these through all the different um releases so wonderful stuff uh we've got dotnet conf has announced calls for speakers is open so um get get your presentations in there is as we always do there is a round-the-world day where we go a whole 24 hours around the world uh 30 minute sessions this is a great time for people uh we have an international audience so all our friends joining us from around the world this is a great time to to speak um and uh you know get get a lot of viewers and it's a very friendly audience and so great opportunity to get your presentations in all right just a few more this is a neat one uh claire tweeted about this yesterday so this is in nuget.org there's a link to open in new get package explorer so this is online so for instance here i just went to you know if you go i'll just show that it's um like if i go to nuget.org and then if i just click on a package so here we'll do a mock and then if i click and open a new package explorer so this is something i always like to see what am i installing i like to look at the source code and so this is all done online opens pretty quickly and then you can explore it through yeah isn't this neat so you can see it like let's see yeah so it has viewers for the different things and um so great to be able to just kind of understand what are you getting in the package i use nuget package explorer extensively i'd install it from the windows store where claire's been maintaining it in there for a while now but i i guess the fact that it's in browser now means it works cross-plat it's the same functionality no matter where it is um do we know what it's built with like how they made it work in the browser like that did they port it from whatever it was to like something that begins with b i'm i think so i'm it's also possible that it was done with uno because i've i've seen something with you know web assembly so i don't know i mean i guess we could be a source right yeah it's the web uh right clicking is not working java applet what no i'm just kidding what is it ctrl shift i here we go console network sources yeah it's uno look at that that's seriously cool it's super cool yeah so and i mean yeah you saw how quickly it opened for relatively large things and so it's just yeah seriously cool it's a if you haven't used package explorer like do it like more like i i use it because i i often i'm debugging like the packages i'm building and so i want to look at like well where did that thing go or i'm trying to figure out what folder did an assembly come from or something if i hit something um but as you'd point out john it's actually incredibly useful just to before you consume a package for the first time or even if you update a package version it's probably worth the two minutes just to go and have a look at the package so you're a little more aware of what the package is bringing in because because nuket packages are so powerful we often just think of them bringing in on like a dll right that you reference but they can bring in ms build logic and they effect they run as you right so they can do anything that you can do on your computer as soon as you bring them in um and so it is it's probably just good practice to every time you update a package or add a new one just go and have a quick check of what's in there and yeah like some of them can include javascript or content you know and so yeah like this one from this jimmy bogard i don't know what i don't trust that guy at all that one probably like adds some back door that controls your smoker exactly no it ruins all your meats so but and it's neat too you can even view you know like the images and all the and yeah yeah so and you'll see on the left also the some of the stuff to do with the what are they calling it health is that what it says yeah so like the ticks and the verifications of like the repository signature or if there's an authentic code back signature um whether it was a deterministic build that produced it so that you can be confident that you could go to the source repo and build from that commit and you would get the exact same output um you know et cetera et cetera so that's all part of this kind of secure supply chain um and like understanding where your dependencies come from et cetera so it's it's a lot of really good info here yeah super slick do you know if this is uh open source package nuka package manager is is open source i'm 99 sure i don't know about the website maybe that is too i'm not sure that's cool like i'm already like looking at you know our latest signalr release javascript out of like you know uh nougat back from i i should say the full framework signalr when we shift javascript on nuget uh yep one feature i'd love to add and i would maybe look into doing it if it was if it is open source is uh downloading like individual dlls i don't don't think you can do that i was trying well i think in the in the desktop one that i use you absolutely can because you can just like right mouse click i think and say like copy this um but i don't know if you try try it john can you right mouse click on something in that lib folder and just like or can you just like pick up one of the files and like let's give it a shot i haven't tried dragging but yeah that's what i typically do um with the windows store version okay so no i couldn't download okay however when i clicked on the dll look at all this information it's giving attributes like pdb sources i guess if it's got source link it gives you a lot of good info like it'll extract all the assembly metadata basically so anything that can be observed in the assembly by loading it in a metadata context um it'll show that for you which is great oh look at this dependencies so up in the upper left i picked depending on the navigable yes website yeah that's cool i like that all right let's see what's in here i'm just that's what we're doing the rest of the show we're just gonna look at this pdb sources what that is cool and yeah links directly over to github that's just some crazy stuff sweet all right okay last one which is also a visualization thing this is from github this is the office of the cto github octo i like how they do that and they've created this thing that's a visualizer for repositories so here they show going through all these different repositories and it dynamically generates this stuff so this this is pretty slick um i the first thing i did after looking at this for a while oh and they go through and show all these different cool repositories and then they talk about also some future ideas of things that you could do as far as showing connections in a repository and kind of like navigating through it so that was neat i went over and checked out the asp.net and net repos and they did not have color coding set up for cs files so i pinged them and they added in dot cs file vision nice so now they did explain like it it still is not going to color in as you go and unless you go at kind of deep levels they only do certain levels of them but they've added in a lot of others like new spec and all sorts of other file types so you can go up here and you can type in you know whatever run time and it takes a little bit you know it's got to go and fetch and and analyze the data um but it's pretty slick and you can link directly to it as well so the whole the office of the cto at github they're doing a lot of cool like visualization and data exploration stuff and so i've been i've followed them on twitter and i've been just kind of keeping an eye on what they're doing so anyways neat stuff and then again like so i guess we'll wait on that so yeah here's the uno platform that i mentioned earlier somebody asked again about about that so there that is and i am done talking i'm ready to learn some more minimal repo or minimal api stuff right well i guess i'll give a quick background of what we mean when we keep talking about these minimal apis in dot net six in asp.net core because the name has gone through a couple of iterations on what it covers and what not and i think it's kind of settling down now based on um how people have interpreted what we call it and how we refer to it and blog posts and whatnot um today is a release date we're in the middle of pushing a new release right now so the stuff that i'm talking about will be a combination of stuff we we've shown in preview six stuff that comes out today in preview seven and then stuff in daily builds because obviously we i i work mostly in daily builds and stefan obviously because he's writing the code and i'm consuming it usually and then giving feedback and reiterating so um first of all if you want to play along with this thing you may have to uh consume bits that are a bit newer than the official previews sometimes um and you know the different people will decide whether they're ready to uh to consume those bits as new as that or not um but the minimal api effort started as i understand it last year between uh maria who's a pm on our on our team and fowler who's uh lurking in the comments today on youtube um and it was initially as i understand it and i want fowler to correct me if i'm wrong um an effort to investigate what would it mean to try and uh simplify uh the code involved with you know starting from zero like a blank cs file to getting your first hello world in an asp.net core app um if we could somehow simplify that because uh doing that today for people who are new to net or new to c-sharp there's a lot of concepts right you know c-sharp is about to release version 10 we've had all these amazing features added to the language over a whole bunch of years and very little if anything or nothing has been deprecated right like you can do it we might add new ways of doing things in c sharp but often you can still do it the old way as well and so as a result the same is true for apis that we build and ship and so if we look at net core and asp.net core in particular folks who have been with us over this last five or six years probably recall we've gone through a few different iterations of the type of code required to boot your application and configure the application all the way from one o where it was it was a lot of code like you would do file new in the templates and now philosophy at that point was you can see everything that's happening there's like 20 lines required to get hello world with what we think are the right default sort of idioms and configuration like reading config from a settings file reading config from the environment variable reading config from the command line if you wanted all that to be on by default you had to call three methods to do that and the first iteration of the templates did that it's um back in the day and so there was a lot of stuff to get from nothing to kind of hello um and as fowler says yeah the good old days uh sounding like a boomer um so we but in version two there was an effort to after we shipped the version one we were like ah a lot of this seems like boilerplate maybe we should be a little more opinionated as a product team about what we think represents a decent set of defaults so that you don't have to have 40 or 50 lines of code to get what we think those defaults could be and perhaps you don't have to reference eight or nine or even ten different packages to get those defaults internally the system we thought was very well layered it's architected well a lot of effort was put into ensuring that the the actual dlls and the apis are factored in a way that they that we can improve the platform over time and you by by ensuring things live in the correct layers and we don't introduce problems with circular dependencies and that type of thing and also that your app doesn't have to take dependencies on lots of things um for to to do whatever it is your app does like pay as you go was one of our philosophies early on right so you you wouldn't have to have stuff if you didn't use it is this live what can i do to prove it's live i am drinking a cup of tea i just made and it's still hot it is very much live i can hit the reset button on my computer but that would probably be a little different um so inversion is pronounced what's that i can pronounce yes we would usually fix that in post you're right yes um so in version two we introduced um the concept of a uh static web host builder factory thing like basically you would go web host dot create default um and instead of saying web host builder dot new web host builder dot add a bunch of stuff dot you know build blah blah blah blah dot run uh you could just say hey give me a builder that has the defaults that you think are right and you know 40 lines went down to effectively three or four um and so we did that in version two and then also in version two we we kind of did some experiments with how we referenced nuget packages and we introduced this idea of like a super meta package that represented a shared framework which was new in.net core two and that was a bit of an abomination and that went through iterations in 2021 and 2-2 before that finally got resolved the way it we ultimately wanted to in version three with um your shared frameworks with ref packs and runtime packs and all these new concepts that got introduced into nougat and ms build and the sdk et cetera cetera so everything got a lot cleaner so there's been this cycle of iterating and trying to identify places where there's a lot of boilerplate to um or even some boilerplate to achieve what we think is a reasonable kind of 80 case there'll always be advanced cases where people need lower level access to things but for the majority case can we make those things easier and so that includes apis and it includes sort of package structure and just the developer user experience and so then in.net uh five uh we we went a step for no done f3 when did we do generic host that was three right so done f3 we also we took the learnings of the web host that we did in two and the foundations of that in one and we genericized it so instead of saying all this hosting goodness that gives you di and configuration and logging and everything in one place in a single composition route for your app let's make that generic so that it's not just for web apps we could in theory use it for any type of app and we introduced the worker template in.net core 3 which utilize this new generic host um and so if we went from like web host dot create to host dot create because now it's generic you don't have the word web in front of it and then we did some glue to kind of bridge the web host world to the host world um and that and that you know survived in dot net 5 and it was it was it was fine it's pretty good and it gives you a lot of power and flexibility but if you look at it there's still a little bit of legacy because of this kind of split between the generic hosting layer and then the web host specific things like you know the support for a startup class um or you know extension methods that are that you want to appear on the builder that are web specific so if you look at a template for a 3-0 app and maybe i'll share my screen now sure yeah so let me uh i've got a few things going on here um but i've if i go in here and i say what version am i using in here all right so i'm using a bunch so let's look at all the sdks i've got i do have a three sdk here so what i'll do is i'll make a 3.x folder then i'll drop a global json in there and there's nothing because i misspelt it and then i'll edit that global.json file and i'll say yeah i want this to be 3.1 dot whatever that was so we scroll back up 3.1.411 okay now if i come back down here and i do version we're now using three one four for one so if i create a new app and here dot net new web uh we'll just do the empty app and i'll put that in my web one and then i do you know code web one we can see here loading loading loading open up there's my program cs right and i'll zoom in a bit for you because i know you like that john yep we've got this kind of this setup in our program main okay we've got main is the obviously the normal entry method of a c-sharp console app basically and we call out to this sort of weird hanging static method which we'll get to a little bit in the future um create host builder uh which takes in the ads as well and then this is where we've got that host dot i talked about so you got host dot create default builder which is the generic host that we introduced in three and then i'm doing it a bit more because someone said zoom in um and then we've got this configure web host defaults which you receive a web builder so you've got kind of a host builder within a host builder in 3x in 5.0 um and that was just kind of due to this evolution that we went through and so then you finally get down to like here's my web specific stuff and then that just effectively shells out to a different class which is your startup class right which everyone kind of knows um and loves all right so that was three if we go back and i do the same i think in five x we didn't change anything stefan did we that was basically the same info no it's basically the same seven in five and like yeah for people who are curious like the generic host is so you can host like windows services and stuff like alongside your your web applications so right that's like the word reasonably introduced right yep in fact if i look at um go back into my three folder and i do net new work dash dash help there's that worker template the details about that worker template that i talked about in in that and if i go ahead and create one of those we can see how that works so if i do work a one i do code for worker one and we open that one up we'll see a very similar thing so here it is this is now not my web app this is a worker app which as stefan just said i typically run as a windows service or maybe a standalone container in a kubernetes cluster or it's you know deploy it to a linux machine and run it using some type of daemon service like system d um but you can see it looks very similar the boot up code to my web application code in fact the only where it starts to differ is down here all this stuff is the same because it's the same hosting pattern and then we go oh but we don't have startup classes in generic host we we have a different pattern for kind of booting the app and in this case you add a hosted service which and you tell yeah there's my worker class and in this case this is kind of the app model for a worker you have a thing that implements an interface or derives from this background service abstract class and then you override some things and that's the app model like that's what you do right and web apps obviously are far more rich and they have a lot more features because it's a web app so that gets us you know through the history of effectively of the the startup stuff fast forward back to what i started talking about which was last year there was an experiment run by fowler and maria to look at what would it mean to create a simpler startup experience for folks who want to build web apps or apis who perhaps are familiar with other ecosystems whether it be javascript or go or python and but you wanted them to do it in c-sharp and so fowler wrote a a library called feather feather http so if i google further http you can see that here's uh the repo and this was this was uh the foundation of of that experiment and that user study so they actually got people into a lab uh remotely because covered um and they got them to run through a tutorial and then they observed what the how they went and they asked some questions at the end and they did the usual kind of user study thing and so you can see here here's this might look familiar now here's this hello world using feather http right which looks much simpler so there's a few things going on here already uh that we can break down so before i even get into the apis this looks very different to a c-sharp program.cs file that we might be used to and that's because it's utilizing top level statements which was a feature that was introduced in c sharp nine i want to say so the last version of c in dot net five and that basically allows you to have the primary entry file for your application typically program.cs historically doesn't need to declare the class and the entry method the main anymore if you have a top level statements file uh it's basically found by the compiler by default and that will be assumed to be the equivalent of your program main okay um and so that that simplifies a whole bunch of things you don't have to declare a namespace or which is always optional but a stat a class and then have a method on it you just say no here's my code simple as that right so you can see here these are just statements these are just c sharp statements they're not in a class they're not anything else and up here we have the more typical usings that you would see at the top of any dot cs file so we've made an evolution we've got to here and as a result of that experiment uh it turned out yeah this this this idea has some legs you know looking to remove certain boilerplate does improve the experience that uh new users to the platform might have because it drastically reduces the amount of concepts that people need to be exposed to to get from i've got the sdk running to i've now seen output from an application for the first time right without having to like ignore a bunch of code i just want to mention as you're pointing out those top level statements and stuff i was hosting um mads christensen on the show and he was he was writing in a visual studio extension and we started playing with that and we just turned on the latest language version in the cs proj and refactored and it worked with like there's tons of boiler boilerplate code and all kinds of usings and all this stuff we moved all the usings to global we did like just refactor and like these huge long verbose methods all of a sudden we're like five lines of code you know it's really pretty so you don't have to i mean you can depending on your use cases or whatever but you can start using this stuff now and refactor your code quite a bit yeah and so i mean it's fair to say i will say um when you say now i think the at the the iteration we're about to talk about.net 6 is where a lot of this stuff really comes together we didn't update our templates for example in net 5 to use top level statements despite it being supported by the language okay um if fowler is asking me to zoom in which one fowler like this is zoomed in quite a lot already can disappear zoom in the console more there we go um just hide our faces that's easier yeah um so let's go to six now so we've seen what you know this is kind of what we could have done in five in terms of top level statements but this was an experiment so what what did we do to take the results of that experiment plus more features that are introduced in c sharp 10 uh you know aka.net six uh to simplify this yet uh even more so if i look at i'm in my 6x folder now so let's just make sure i'm using the 6x version i am excellent uh so let's go in here and we'll do dot net new web web one in this folder okay and then i'll open up that in vs code and then we can see what this looks like now boom right look at that so it's even less code than we had in the feather experiment because something you alluded to now the code is too big now we need to zoom back out america well the user you alluded to was global usings right so global usings is a feature of c-sharp 10 which enables you to in c-sharp anywhere you can define it using as being global for that project so instead of just saying using blur you can say global using blur but we don't have any usings here so how is that working well we took the global using feature and then we built an sdk level feature an ms build feature effectively that's implemented in the sdk that that we call implicit usings and it uses the c sharp 10 global usings feature to let you define global usings in ms build so they become implicit to your code because they're not in your code they just get added by the sdk or by your own ms build files that are interpreted by the sdk and then by default in net six for new projects created uh we do this we just in we just imply that you were going to use a certain amount of global using so all of those usings that we saw in this example here they're on by default you get those in every cs file in an asp.net core 6 app by default if you create a new project now in a little caveat here in preview 7 the release going out today that's only guarded by does your project target.net 6. so if you take an existing project and you change the tfm in the project file so i go to my project file and i set this to net60 like it is here then i just get the usings right like so that early feedback on that was that that that can cause some issues for existing projects so in in the next release which is already being worked on now that will be behind a flag that looks like this so new projects will actually have this property that says implicit usings enable and that's what will turn them on rather than automatically turning them on based on tfm so if you upgrade an existing project to net 6 and you want the implicit usings you'll have to also add this property to get them okay so that's just something i wanted to say there so and that's why that's why this is can that break stuff potentially it can potentially and in reality it did break a couple of things in some very complicated repos when we tried that internally like the net repo and the asb net core repo um and the the usual way in that it can break is with type conflicts and so if you have two classes or two types in the in the in the universe of things that you depend on or reference in your project that have the exact same class name and then you import both namespaces you'll get a type conflict because the compiler can't doesn't know if you meant task from system dot threading blah blah blah or if you meant task from ms bill dot blah blah if you reference both and the way to work around that is you can use an alias right so using supports aliases now you can say using foobar is equal to your microsoft.asp.net core whatever i can say hey that that now is that thing right or you can also do it for a specific type so you can bring in you can alias a specific type that way um as well so now i can refer to this using this and just change it completely and i can break the conflict that way okay so now it's no longer a conflict so that's how you can work on that if you hit that issue someone asked in the chat um can you add your own implicit usings or global usings yes you can and so because this is an sdk feature once you've opted into implicit usings like this in fact you don't even need to opt into implicit usings because they're not treated as implicit if you specify them explicitly in a ms build file you can in an item group and again this is going to be the case in the next release not the release that's out today uh because we've made some adjustments to this is you can define them using a using item like this okay and then you'll say include if i wanted to include everything in the asp.net core dot mvc namespace which is complete overkill but say i wanted to do that you could do that and now that namespace is automatically included in every cs file because that will emit a global using inside a generated cs file that you'll see that the compiler will see but is not in your source code okay right and you can do that in the nuget package and if it's just your own project you can use the c sharp feature as well and just put it in a separate file that's right so you can if you just have one project and you just want to do this in one project you can choose like just put it in a cs file called whatever you like globalusings.cs if you want um and the compiler will find them but if you want to compose them via ms build so that you know put them in a directory dot build.props or as stefan said put them in a nuget package so that when someone adds your package they get a using i'd recommend that you guard that with an ms build property they have to opt into similar to what we're doing if you do that or you want to modify an existing one this is an ms build item so you can modify it and uh um change it uh compose it uh with other ones using all the normal ms build idioms so i can change this to you know update you know i can change this to remove and i can do all i can put a condition on this right i can do condition equals and do an ms build expression here so that only applies in certain conditions uh someone asks a great question does it support stars oh i wish it would that would that requires a language feature and i very very much would love the ability to be able to do that and have the compiler understand that right but that's not the case today it is something that's been talked about before and it's a reminder to me and go to go and potentially uh chase up the the language team to suggest that and see where if that could land so yes that will be possible in the next release okay similar question on folder scoped and i'm i'd assume that's the same too right um which one sorry i i think this is the same thing as basically globbing uh there's file no so there's there is no support for folder scope usings there is something called a file scoped namespace declaration which is a little bit different which we'll talk about in a moment but the the the cs language still doesn't have support for scoping based on directory structure it did come up in the language design meetings i believe for these features but i looked at the some of the notes and the pushback on it as i understand it was that today the compiler doesn't do anything with regards to paths or the file system like it doesn't understand where files are there's no ordering implications in cs there's no depth implications with regards to where the file came from in the file system and they just that's somewhat a principle and they don't want to introduce that in the compiler um we do it in razer as the user pointed out so that in in razer will actually automatically infer namespace from the folder and the tooling does it today if you create a folder and then you add a file the template will set the namespace for that file to be based on the um the folder path but the compiler itself doesn't do that so that's where we're at with that um just quickly to finish off the the feature of using that's coming as well you'll also be able to specify an alias in here so you could for example as i did before you could do the same thing by doing that and now that will be available everywhere in every file in your project foobar will will resolve to mvc the other thing you can do is do static usings so you could for example change one of our new types that's been introduced you could fully qualify um or quickly qualify results um to be to point at that um and that would bring that in uh without you having to specify um sorry that should be this way that would then allow you to say the method on the results class which is static are now always available and i don't have to um identify them or resolve them using the type name okay so that's that is equivalent to those haven't seen that before that equivalent to doing this which now makes every static method or every static member on this type available in this scope right so i could just say json and it shows up because it's a method on results okay so we have full support for all styles of using statements with regards to importing things into your language scope uh in the next version obviously real quick question and and you know like just because we do have some beginners watching what is the what is the you know like elevator pitch what is the high level on what people need to know about ms build right so that's a good question so because dot net is um a compiled like i should say sorry c sharp is a compiled language and dot net is a type c system that runs on something called intermediate language right you typically write your source code in a language like c sharp or f sharp or visual basic and then you run it through a tool chain to produce il or intermediate language that's what the net runtime knows how to execute that's different to something like node where you write javascript and it executes javascript now you could write typescript right and then you'd want run it on node you would have to run that through a compiler so you start with typescript it emits javascript and then you run javascript as the in node.net you in this case type c sharp you run it through a compiler it emits intermediate language or il and then that runs on the runtime that middle step where you're where you're running it through a tool chain and as foul says don't learn ms build until you need to that middle where you're running it through a tool chain um there is a standalone c-sharp compiler it's an executable it's csc.exe but you don't ever really use that directly what you use directly is the net cli so you say like.net build right so you come out here and you would say you know dot net build something under the covers that is invoking a tool chain which is coordinated by ms build ms build is the build um system that.net uses by default there are other ones uh but the bamas build is the one that we ship and that is used by default and so you give it like make with xml and it's xml right for reasons for historical reasons it's been around for over 20 years and it's also the file format that our ides understand like here i'm using visual studio code with omnishop running and it knows how to interpret these cs proj files these ms build files as does visual studio you open a net project a dot net project is an ms build file so it is kind of the unit of structure and it's the unit of of of building and build orchestration in node you'll see um scripts being used for this so you'll have like a packages json script where you define all of your um define your references to dependencies on npm packages but you can also put tasks in that file and then you can use npm to execute those tasks so you can kind of think of it that way but yeah that's all ms build is you typically don't have to get familiar with ms build as fowler said as part of being a normal.net dev until you get into more advanced scenarios cool all right so staying in this template now we can see it's really simple right we have this web application.createbuilder which returns a builder similar to before um at this stage in here i can do stuff to configure the builder before i run build the most common thing you would do is add services to the bi container right and so if we think back to the 3x application and the 5x or we had a startup class where we would traditionally be configuring our services and then setting up our middleware pipeline to now you would do that here so you would configure your services in here you might also configure the configuration providers in here and then after you call build you get back an app and the app is the thing that you configure your middleware on so here i'm doing a map get which is an example of one of the new minimal apis that we added in net six that says hey when you get a request for slash can you run this delegate here and this delegate is a anonymous lambda so you say map git is new i think i've i've seen that method before so there this is a new overload mapget has been around since dot net core 2.1 because i think i wrote the original version of it and i had to fight fowler to get it in he didn't want it um but you would have come a long way um and so this is a new overload that knows how to take a standard delegate that has no type information on it whatsoever other than the fact it returns a string and turn that into the underlying delegate type that the asp.net core pipeline understands we call it the request delegate and that's a specific signature that is used that all middleware has to implement uh which basically means it has to take the same parameters and it has to return the same values and that's what we build up the middleware pipeline with so now we have a lot more support for taking delegates with different shapes and basically turning them into a request delegate under the scene under under the covers and then plugging them into the middleware pipeline and that's what stefan's been working so hard on this release is this whole mechanism for not only this part which is let's simplify and create minimal versions of the boot up logic but let's also create basically a minimal framework for mapping endpoints to routes in asp.net language right so you can think of this as a route this is a route pattern effectively it actually is this is exactly what this gets used for and then this is an endpoint delegate or a minimal action or we've given it a few different names this isn't yeah a route handler like like you could give it you could give kind of give it different names sorry i have a short question on this yeah like i get what that is because i've seen the code and i understand there's this delegate and all that kind of stuff is it ever possible to change that delegate syntax so you don't need that operator at the beginning so the question you're asking if i if i understand is that why do i have to do this at the beginning yeah and i'm why can't i just do that for example exactly and i'm cool with typing it but i just wonder like you're teaching somebody new is it so well not the first person to have to make that comment okay let me give you the same answer that i've given other people and i've heard other people reply with as well no one blinks an eyelid in javascript when the first thing you do is pass a delegate we don't just don't call them delegates right they call them functions you pass a a lambda function to some other function invocation in order to say hey run this when this thing happens like that is like javascript 101 if you're learning express in node for example doing hello world you will do that in dot net for some reason we introduced lambdas back in what dot net two dot net three someone tell me how much version it was um it was a precursor to link like you had to have them to support link right because you passed these to the link extension methods and so we've had them i think is since dot net 2 which means they've been there since 2005. right bob that's correct since 2000 that's ga they were in previews before that yet there is still in our community including and it's not just you john i'm like i'm saying people yeah i'm trying to speak on behalf of that's right right and they're like do we still why do we have to do this this seems like some ceremony like i don't know how to like this is so generic like a method that takes two strings like it's so constraining we would never be able to add overlays of anything if we did this like a method that's the only problem yeah you know but you're making me think we could do it right because okay so right now we have the we take the route as the first parameter as damian says and then the second parameter used to take specifically what's called a request delegate right which is a funk of hp context to task now we take delegate which to geek out a little bit this gets pretty intense like we couldn't do this before c sharp 10 existed without like a bunch of ugly casting like this point in the original template this thing that returned to hello world you had to explicitly cast that to a funk of string um but now in c sharp 10 there's this concept of a natural type for lambdas basically it just means that c sharp 10 like figures it out like what you would really want to cast this thing to um this thing is so hard to use like you never get it right the first time yeah oh man okay i see yeah so you're trying to use an overload that takes the next parameter um i don't have to i don't think you do i mean that works for middleware but for endpoints since it's that what i should have done no how do i how do i get the overload that takes request delegate okay yeah there's no next for request delegate you just return the task directly middleware can take a next function so yeah and then you can just do like contacts.response.right async whatever um yeah and that will give you what you want all right so this is that is the functional equivalent of this other than the path right and as as stefan just pointed out it was not possible for us to support this until c-sharp in c-sharp 10 added new language features with uh to do with how they infer signature delegate types from um from what you pass if i hover over this you'll see that the intellisense the statement completion help here is actually saying this method accepts delegate like it just accepts delegate that's like any method basically can be passed to this which means that you can also do stuff like this i can pass what's called a method group and we're going with i mean these names all mean something um but you know it's just kind of like so if i do i'll do a string sorry so if i turn the string and i call this hello world right and then from this i do return hello world that is now valid so i created a local function which is a c sharp nine feature i believe local function inside my top level statements file and then from that i return a string and then i pass that as a method group to here and the compiler correctly can resolve a method group to a delegate which it couldn't do before in the same and then also can take an anonymous lambda and do the same thing as well which is you know just awesome because it means that we can now basically have a method that says give me a pointer to any method i don't care what it is and then we will do our best to convert that into a request delegate and if we can't then you know we'll tell you we can't i guess what i i guess what i was asking or thinking is that there could be an overload that just takes a string and wraps it in a delegate but that's what you don't know how useful that is it's possible but that's definitely yeah as you just pointed out how useful is that really because you can't stop doing that like instantly once you've learned how to do it and the second thing is there's only there are overload rules we can only have so many methods called map get they all have to be different with regards to the parameters they accept and there's like a whole bunch of complicated rules to do with overload resolution in c sharp and so if we use the the overload that is two parameters that accepts a string to do this it kind of feels like a waste there's probably a better use case of an overload of map get that takes two strings that we'll land on in the future and it's not this one because as we just said you'll stop using this instantly like yeah how many things are you just going to retain a string from sorry right yeah that's fair it would and then we struggled i was just before this i was on another call and we were like struggling with like okay you can make for for a course for blazer and we're like okay we can make something super simple for hello world but then you immediately have to drop it and learn another concept so it's a waste of your time really so right so someone just asked yeah can you do this yeah because we're combining a bunch of different language features here and so you i'll pause at this moment to say what this has enabled is that when we go on a learning journey with a with a with a new user and we we develop some type of you know story arc or we let the user drive the story arc much like what we're doing here we're responding to comments you'll see how i think this is much more progressive like there is we're not having to see concepts introduced in the language or the framework until someone is ready until they ask the question or we're ready to tell them as the storyteller so yeah i can change that string literal that i have before into an interpolated string in the same method and i can say yeah you put a dollar in front of a string literal it turns it into an interpolated string in c sharp and then i can use the curly brace syntax to template the interpolated string and pass in whatever value i want to be inserted into the string and that was a nice step from it was just a string so now it's an interpolated string and that's a good example for why having just a string overload might not be as convenient as you think because if it was a string overload it wouldn't work the same like the time would always be the same for every request as opposed to right time of the request so yeah giving people that overload might actually cause problems down the road you know and that's interesting and that's really subtle right because that gets to like lifetime and values and like delayed execution and all these type of things that can be difficult and it's not that's not just a c-sharp thing that absolutely would occur in javascript as well anything that can accept a method versus accepting a value and then getting a mental map of well when does this code execute like i understand that line 8 is going to execute when the application starts and it executes before run but this won't execute until a request to this comes along right and getting that mental model is incredibly important for a learner as they're learning how web application sort of object models work and application models work so yeah this code all runs at the beginning you know this is where your app starts running and then these little snippets are what runs when they match uh when requests match these route patterns that you passed in sorry so and since these all are the same route pattern it's going to execute all three of those right well exactly uh this is invalid what you'll get actually is an error when you try and run this application um i think is it when you run stefan or is it when you the first request comes in i can't remember i think it's during the request it will say that it can't find a single ambiguous or something or something yeah yeah it'll like it'll say what you said john i've got three endpoint three routes that match the incoming request i don't know which one i can't disambiguate that so this is invalid um typically you would obviously have these as you know hello1 and hello 2 and hello 3 or something like that and then that would be fine are we going to have time to show parameters i know we're right so let me fast forward all right yeah so we basically our hard stop is in a half hour from now okay okay that's good that that but that's a good reminder so a couple minutes to wrap this stage up and then we'll go over to my other project which is more fully fleshed and we can talk about um some of the the parameter support and response report uh support that uh sorry that stefan's talking about so but there's a lot of different language features that have come together here in this template that you'll see uh a comment some of in preview seven and then some more of in rc1 when it comes out in another month or so from now um yeah c eight features c sharp nine features and c sharp ten features all coming together to uh create this more minimal approach um to building applications one other one i wanted to point out that we're now opting into by default is this one so in c-sharp eight uh we introduced the concept of nullable reference types in c-sharp and then it's been a bit of a journey for people to get their code updated and when i say people i mean us to get asp.net core and the net runtime um updated to actually use the nullable annotations to to to to use this language feature to guard against one of the most um frustrating errors that you can experience as a net developer which is uh object reference not set to an instance of an object and so we turn this on by default now in new projects so if you know we have another we have nullable enabled in new projects that you create in dotnet six and so that will introduce slight changes to some scenarios where the compiler is more strict effectively about the types that you can bring into parameters and what you can reference and de-reference and it'll give you warnings if you do things that could result potentially in a null reference error and you fix those warnings by using new syntax to tell the compiler more information about yeah no i expect this to be nullable that's okay let me declare it with the question mark to say it's nullable so that's also on in these new templates okay so this was empty web obviously this is where people start let's have a look at where you might end up going so i have this playground repo where i've been experimenting with these features as they get built in the daily builds and then also as a quasi set of examples of what the type of thing that you can do um quickly if you want to use these nightly bills i keep talking about you can go to the dotnet installer repo on github and then if you scroll down in the readme if you're on windows this is the link you want right here which gives you the windows x64 installer for the main branch which is the latest latest latest and if you click on installer it'll download uh the msi uh usually windows the smart screen on windows doesn't like it you'll have to like tell it no really trust this it's fine i know where it comes from yes please run it because it's not signed in the same way that our generally released bits are but if you get through all those hurdles you can install uh the same type of bits that i'm using here and get these really really fresh hot bits all right so minimal api playground on the damien edwards repo what is in here so if i go into source i've got three folders here or three projects one is the playground where i've just got like a whole bunch of random stuff including stuff that will probably never ship some experiments some things where i hide things away to make it look like it's in the framework but it's not and then a couple that are a little more paired down a little more realistic so for example a to-do application that uses dapper for for data persistence and you can see in here like it has one file it has program.cs the whole app is just one file and if i open on that you can see it's using a bunch of the stuff we talked about um i don't have any using statements for asp.net or for like system or system.threading or any of the typical stuff they're implied because i get those from the implicit usings feature but then i've just imported the things that are unique to my program so my usings is a lot more cleaner right so then you see your builder application like you you that we showed before and then in this phase here before i call build i'm adding my um types to the di container so that they're available later on in the application in this case because i'm using dapper i just have to add um the sql lite connection type and then i use a factory here so that every time someone asks for a sql like connection i'll run this delegate and it'll just create a new sqlite connection using this connection string which i've hard coded in this case and then once it's built we'll ignore ensure db you see the typical type of stuff that you may have seen in your startup class before but to stefan's point now you're going to see some more advanced examples of this hey we can take any delegate now and we'll do some magic for you so here's the two that we were playing around with before right hello world and this is an example of hello world that returns an object rather than returning a string so here i'm returning what c sharp calls an anonymous type right it's basically it's like new object on the fly with a property called hello with a value of world that's an anonymous type and what we'll do for you now is anything that you return from one of these delegates that isn't some that isn't irresult which is a new type we'll talk about in a minute um just get serialized as json by default that's what that's just what happens that's an opinion you can't change it that is what you get if you pass a delegate to map get on that post or map put map delete and it's not something that we will otherwise process separately it'll just get serialized to json so that's our new sort of default scenario for these style of apis you can write more code to make it return something that you want explicitly but if you just return an object it will get serialized as json so let's have a look at some slightly more advanced scenarios so here's the first one right if i go to slash to do's i want to return all the to-do's in my application so here's my lambda that i'm passing in as the delegate to run when this route is matched but now it accepts a parameter as stefan was saying before so where does this parameter value come from well that's where some of the magic it now exists in our system or i should say the conventions that are based in the system that you can't change the conventions that are there um uh you can use attributes which i mean you can use attributes work pretty well so it's not here but like attributes override any conventions um and that's also a new c 10 feature you didn't used to be able to have attributes atlantis that's a very good point thank you for pointing that out so we have a convention by default but you can override it through i guess you could call it configuration convention over configuration so you can put some configuration on your parameters by decorating them with attributes which you couldn't do before in lambdas now you can and then we'll use that to change where it comes from so where is this going to come from by default well new feature in the di container in.net 6 enables us to know that sql like can a sqlite connection is registered as a type a resolvable type in the di container so because i ran this line up here that said if someone asks for sql light please give them this minimal apis as a framework can go oh i know this is in the di container so i'm going to populate this db parameter from the di container you just do that by default it's very similar to how today in a controller if you take this in a constructor parameter by default we know you know we populate that from the di container right it's basically the same kind of thing but we had to implement a new di feature to get it to work in this scenario so that's cool that's the first type of parameter that you can take in let's scroll down until we see a method that looks a bit different here we go line 31 we can see now that my route pattern includes a route parameter that's the curly brace syntax here i'm defining part of the path as being dynamic basically i want to bind to whatever appears after to do's to a route parameter called id all right so now i have a route parameter and this route will only match if there's something to put in that route parameter and then my method or my delegate takes in an extra parameter now which matches the names match right the parameter name here is id the route parameter name is id and so by default the framework will bind those together for you in this case it's also declaring it as an int so the framework will attempt to parse whatever you put into here as an int right now if it's not an int stefan what happens um your method never gets called and we'll return a 400 um and we'll uh log an error basically saying that we weren't able to parse it right in the parameter so where i s in the route pattern could i say in colon id or something like you could so that's called a route constraint and i will admit i personally think rap constraints i think what you might think would happen isn't what actually happens it can be a little confusing to understand how routing and its rules join with the rules of whatever part of asp.net is involved in invoking your code because in mvc there's kind of a set of rules and in minimal apis there's a set of rules in razer pages you can bind to query string and path stuff or wrap parameters in certain parts as well there's a set of rules about what will happen what stefan just said is that the route will match so we'll go okay if i pass foo here we'll say that matches but then we'll look at the method and we'll go yeah but i can't turn foo into a into an int so it'll automatically respond on your behalf and say this was a bad request because the value that you sent me isn't i can't turn into an end if i then do what john said and i say let's put an int on this then that gives extra information to the routing system and then the routing system will make a decision about what to return is my understanding off the top of my head instead of minimal apis being the thing that does that right so i think what happens if you put an int here is that it get registered as a route constraint which means the route will still match but the constraint will fail and so then routing will return i think a 400 i think it actually returns the same thing it returns a 400 but it does it for a slightly different reason does that make sense sean yeah yeah so i can understand why perhaps people might think if you put an int here like if i did id colin int to say that this should be only for ins that then i could also have slash to do's slash foo colon string and then they they would both be valid routes and like the right thing would happen but it won't because they both have the same number of parameters and they're both prefixed with the same path the routing system will actually say well it'll it'll so it'll do something different based on whether the constraint applies or not but it doesn't perhaps do what you think it might do where you could have a method that takes a string and one that takes an int and you could declare the routes within 10 string and then they would kind of co-exist it doesn't really work that way because that's just how routing works one other question just as as we're looking at this and and janiscu kind of summed it up but i was thinking this too like obviously like we've we've simplified things we've like gotten rid of a lot of boilerplate but now we've got a long kind of unstructured thing we could break th we could refactor that like right i could say you know map to do's and put those all in a function and and like kind of just call each of those separately right yeah so that's a really good point and again i think this is something that we see quite commonly as feedback in the dotnet community um because of just the history of our framework and how we talk about languages and how what the tooling defaults are you know every type is a separate cs file et cetera and i think ultimately what we've decided as a as a framework design team for this is that we want the composition and the organization to be completely up to the user and they use whatever language features or every ever ever code separation features they want in order to break up this this you know their application using minimal in any way they want we tend to show it all in one file because it's so it's just a good way of communicating lots of stuff and like frankly for me personally if i had a to-do zap that was this simple i would just keep it in one file like it's a file that is less than 96 well it's 96 lines long and it is my complete application right and if i was running it in a in some type of orchestration container or running in the cloud provider that did like authentication for me i used you know azure easy auth for example so i didn't need any auth in here because i don't need to do any user specific things um it takes care of logging for me because we do default logging and so it would be configured by the cloud provider or maybe by the orchestration engine like kubernetes those are concepts and concerns that could be dealt with outside of the app so that i because they're handled by the platform the app is running on that's a pattern that we see more commonly now in things like azure functions or any type of orchestrated sort of microservices style system is that some of these cross-cutting concerns are actually taken out of the application code and baked into a layer underneath it so that's just one example there are other examples of why you might want to do this could just be personal choice but yes you can use any c-sharp language feature that you want to organize the code in any way that you want but ultimately you have to call this static method of this method sorry and pass in a delegate that's ultimately what it comes down to we do not have type initialization so we will not new up a class for you like we do for controllers um and inject things into them there are examples of people in the community already extending this and building that type of functionality so they're building like a mini framework on top of a mini framework um to add a little thing that they like to do in their application yeah and as far as the people who are looking for like different ways to organize their project another thing that i would like to point out um which is a thing that i think we have trouble communicating because we're introducing this new host along with these like new mackit and map post overloads at the same time and since we're excited both we tend to present them together um these map get and map post functions are just extension methods on i endpoint route building builder right so in your startup class you can call use endpoint so you can get your point builder and you can call all these same methods and get all the you know new you know service injection into parameters into napkin and all that kind of stuff um without necessarily even having to use like the new web application builder also for those of you who might be interested in like using these kind of new features but want to initialize a class we have a new public type called request delegate factory that these new like map kit map post overloads used internally and that gives you even more control um so you have a lot of options kind of how to compose these pieces um it's not all or nothing you can kind of take the bits you like but you know for the skin you stand up maybe and showing you know and all the new ideas and if you're really advanced and you want to go like full-on you could just look at the source code for across delegate factory and say i want to invent my own set of conventions for the types of delegates or methods that i want to be able to be turned in and plugged directly into the middleware pipeline and just copy the code that you want from request delegate factory make your own like we don't support um extensibility that plugs into request delegate factory today with regards to the cogeneration part but you could just take the code and do whatever you want like that that's one of the value that's one of the values of open source right i would love to see like more little micro frameworks appear like we had carter in the past and nancy before that but there were examples of uh mini frameworks uh which you know carter still exists and there's a fantastic choice for people who want that style and the whole point of building a framework is that you have a set of of opinions that you want to become idioms for how people build or compose the application when they use that framework that's all a framework really is right so asp.net core has a core set of functionality that you can plug on top and then it has a bunch of frameworks to sit on top of that that introduce their own conventions and idioms and extensibility points to change how they work all we've done here all we've done here is we've built a new one that sits basically directly on top of routing that's kind of the way to think about it which was the work that we did in net core 3 to introduce the concept of routing and endpoints as like a global thing that's in the pipeline now and we plugged mvc into it and etc etc now we've kind of built a slight layer on top of that but then as stefan just said it's also kind of underneath it because of the request delegate factory thing like it's really it's kind of a nice gray band that sits just on top of raw middleware that lets you be very expressive about just here's a method it has some parameters and returns a thing can you just run that when a request comes in please that's really what it comes down to so here's looking at his point that this is just an extension method that exists on the i endpoint route builder which is something that's existed in the framework for a few versions now okay so i think david's worried we're gonna run out of yeah we have 15 minutes left and he's got a hole yeah that's fine i wanted to quickly say also when we were talking about the routing and what happens when you add a constraint before is that it'll act routing will actually return a 404 so if you for example if i had constrained this with int and then i pass foo the routing system will go foo is not an int that route doesn't exist 404 right okay as opposed to us we would return a 400 if you got to here all right so that's that type of thing now i've got a complex type down here all right fellas like show all the features yeah okay like that's why we usually have more than one show fowler it's like saying you do your architecture talk in one show [Laughter] um so here we're taking a complex type but it's not one that's registered in di so what do we do by default this one comes from di so the system gives you that from di this one because it's a post we will automatically try and bind that from the request body right we but we json to serialize the request body into this that's effectively what happens okay so now i have a to to-do that came from jason and i can use that inside here to do whatever i want let's see if there's any more examples here no i'm going to go back to a different file then to show some of these other ones or i could just show you in code let's do that let's write some code all right so what fowler was trying to uh say i'm just going to copy and paste one of these codes and all uh things and i'll change it as we go so i'll create this one so i'll use this one this is one that we've been using and we'll just take one of these methods let's take this one so as an aside this new builder the use developer exception page is now there you don't have to call that uh anymore that's you right that's new and number three rc though not in preview server oh is it really i think yeah i think so okay that's cool um all right so let's just ignore the squiggles just because i just haven't defined you know these types i copied over what's important is that i have a map post i've done some things and we talked about how things are uh inferred here like yeah this comes from the body this comes from services stefan mentioned before that you can override that so you can be explicit i can say um from a service here and then that tells the framework that i want that to come from the service container explicitly and it'll fail if it can't find it right i can also be explicit about what comes from the body like so as opposed to query string or yeah and these are really familiar to folks who have done this in mvc and razer pages it's basically the exact same functionality uh but now mapped to kind of this layer okay so you can do that as well to get more control if you don't want things to be automatic all the time so the other thing is about well okay what is this return we saw examples of methods that returned strings and then we quickly saw an example of one that returns an object and i said it jason serializes but this one is returning something else it's calling into this results class and it's returning the result of calling created and if i hover over that you can see that created returns an i result so iresult is a is a new type introduced in asp.net core 6 as part of the minimal api effort and it's effectively the equivalent of i action result from mvc but paired all the way down to be the bare minimum of what would it mean for a middleware or an endpoint handler to say i i just want to return the thing that you're going to execute on my behalf that's the easy way to think about it right my result if we look at the actual contract for irresult you'll see it's very simple so if i return an irresult what happens well minimal apis sees that your returns an irresult it has a single method on it called execute async and it takes a context it looks almost identical to a middleware all right a middleware takes in a request in a context and then returns something sometimes by by doing something this is just a formalization of something that we know is going to execute a result based on the fact that we called your method that's that's all it really is so in this case we have a helper method in the framework that does this for you you say hey doc in this case i want to return a status 201 created so we have a created method that does that for you and takes in a uri which will be set as the location header so you can say we was created here's the location that it was created at and it can also take in an optional object that we will use to serialize the response body so you you can return what was created as well if anyone has ever used the api controller feature in mvc that we introduced in asp.net core 3 this will probably seem quite familiar because some of these conventions are also part of that system and then the other thing we can do with this as an extension is we can take a bunch of this metadata with a little bit more help which i'll show in a second and we can describe an open api document or a swagger document as well about your apis um automatically for you so for that one i might actually open the project that does that so we can run it okay and we can see that in in real time another thing i want to throw out with regards to like the attributes is it doesn't only work on the parameters if you want to throw like an authorized attribute on your method um that that can work um as well as like before with the map get with the old overloads you could call like i think it was require authorization extension method yep that's right yeah good so let me get a lot of questions on that go into here i'm going to go into the minimal api playground and hopefully it just works when i run it [Laughter] i didn't break it it's building it's thinking really hard yeah do we blame the stream for this okay no yeah but we might as well okay that's just a warning that's fine it's running okay perfect so let me uh take this we'll go and have a look at what's running here all right so i got my hello world right and i know that in this thing if i go to slash docs in this app it takes me to the swashbuckle front end okay the swagger front end so i can try out some things and you can see that we're getting a whole bunch of metadata describing the apis in my application that is coming through in this case to the swagger ui or i could go to openapi.json and get it as a as a swagger document or an open api a document so how did i achieve that how is it that the framework knows if i look at this uh post uh on whether it will post to to-do's and it describes the request body here like how does it know that it takes a request body that looks you know has an id has a title is complete and how does it know that it accepts application.json well that's a that's a combination of two things it's a combination of our defaults the conventions i said before that we just serialize stuff as json and we deserialize stuff as json by default so there's that set of defaults there's what you put on your method so the method parameters if i look at this file over here and i go and look at this program.cs and we look at these parameters if i find my map post so here it is it knows that it takes it to do so the framework will describe that automatically if you add swashbuckles swashbuckle automatically picks up all the metadata that the framework puts in via the api explorer type and so we do that on your behalf but then we can also add other metadata so we can see down here that not only does it know about the stuff from my type signature it knows about stuff that i told it so i said yeah and i want you to have to name this method add to do whenever you describe it somewhere i want you to know that it can produce a validation problem which is a certain type of response and i also want you to know that it can produce a to-do with a status code of 201 created okay and what does that map to well this line here in my example which i'm using some extra code that doesn't ship in the framework i'm plugging in a validation library i'm saying look this method can return a validation problem up here so i tell the framework that that's the case and then down here you can see i returned created a route and so down here i tell it about that case as well and that's how the framework is able to say for this method there are these types of responses there's a 201 which is the created response success and that's going to include the thing that that got created there's the type but it can also return a bad request with a type of validation problem plus json okay and here's what that type will look like so again this is possible in mvc today we introduce support for some of this type of stuff in asp.net core 3 with the api controller and the api controller conventions features and then you can decorate your action methods with attributes to say hey this produce this method produces this type of response and it uses and it returns this kind of type and then the framework would take all that information feed it into api explorer so that frameworks like end swag and swashbuckle can can produce open api docs in minimal apis it's just more streamlined that's really what it comes down to it's a little bit more opinionated and there's less ceremony involved in doing that description as stefan just said before you could instead of using the extension methods you could use the attributes up here instead if you wanted to you could say producers right and here's the attribute from nbc if you put that on there it'll work the exact same way as it does by doing it through the extension methods we let you choose either way also if i'd factored this out into its own method and i passed it as a method group like i did previously i could also put the attributes on that method and they would still get discovered and all that would work the way that you expect so kind of going back to the principle we said before john when you said what if the user wants to structure this differently we support all those ways you want to put the method on a different type as a static as a static method and put attributes on it it'll work you want to pass it as an inline lander and put attributes on it it'll work you want to pass it as an inline lambda and use extension methods to add metadata that will work right all those ways work doesn't matter how you want to compose or structure your apis you can describe them as well using you know whatever method is is fits best with how you chose to to put them together okay we're at a hard stop now because we have another show that's that's just about starts oh okay so this is great tons of i mean we've had tons of great questions i think obviously we're gonna need to come back and go go more into this and especially you know keep following up as it as it continues to change right yeah um so for people i've shared the link to your minimal api playground and then where else is best for people to keep up with this just as so given how much churn is thought chen like we're we're basically finishing the features in this right now as part of the rc1 release um and so we've got a bunch of folks doing you can look at the minimal api playground repo that you pointed out to see some examples of how things are landing i haven't updated this in the last couple of weeks i need to do that to utilize some of the new features that are coming you can also look at the asp.net core repo and look at the issues to do with the there's like a feature dash minimal apis label and if you look at those issues and look at the code associated with those issues you can see the changes live as they're coming in and play with them awesome yeah there are two labels there's also feature dash minimal hosting yes for the hosting stuff yeah okay i'll get that from you and i'll add it to our um community links for the week awesome all right well we've got to wrap up now or the the people on the next show will beat me up so uh but thank you so much this is amazing stuff and thanks for all the questions today too absolutely all right thanks everyone [Music] you
Info
Channel: dotnet
Views: 12,225
Rating: undefined out of 5
Keywords:
Id: aMrKGC7CnEk
Channel Id: undefined
Length: 88min 9sec (5289 seconds)
Published: Tue Aug 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.