The .NET Docs Show - .NET 6: Getting started with Minimal APIs

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] do [Music] do [Music] so [Music] do [Music] do [Music] do [Music] and welcome to 60 minutes of unscripted.net entertainment as doctorsof.net we prescribe healthychoicesin.net i'm your host cam sober and we are here with our co-hosts david pine and scott addy um we would like to welcome today's guest nick nick i have to apologize i was late to the pre-show i'm not even going to attempt to butcher your last name i'll let you do that on your own nick introduce yourself please yeah so hello everybody uh i'm nick chapstos i am a microsoft mvp for developer technologies um i have been for a few years now i'm also a senior engineering manager at a company here in london called checkout.com and i have been living in london for the past 10 years and some of you may know me from my youtube channel where i upload dot net and c sharp videos and the odd video that is not really.net in c sharp it's more general uh yeah that's me and very excited to talk to you about minimal apis today well that's awesome because we're all three like um like web people and we were just talking about minimal apis last week i know scott and i were anyway and um i'm really interested to hear you know the value prop because i like my controllers um our guest calls out in the chat one hotly debated feature it almost feels like we're going into a tabs versus spaces debate for the next hour or or or you know what's even worse than a tabs versus spaces debate is how many spaces two or four oh come on now we all know it's just semicolons all the way that's all you need all right so how do you guys feel about doing a checkup let's do it well you're getting lots of love here in the chat so this is great i'm very very happy for that um everyone's excited to see you nick yeah i'm excited to be here i've been watching the show for quite some time actually oh awesome that's that's great happy to hear it um so for today's checkup we're going to be looking at instead of a dock we're actually going to look at something that's more of a living doc from our good friend my mentor david fowler who is very very active on github and you'll see many gists of his take take hold and gain lots of popularity uh this being one of them so minimal apis at a glance if we could just scroll the link on the bottom because no one wants to copy on this amazing id oh yeah you know i'm i'm just it's the the morning after halloween and i am just i'm worried uh so you're going to want to check out um https aka dot ms forward slash minimal hyphen apis that is going to get you to this gist so david fowler put together minimal apis at a glance and he kind of has like the high level nodes here for application request handling uh authorization cores open api and advanced and each of them linked you know appropriately so at a very very high level minimal apis are basically a way to i think rapidly prototype and i'm going to kind of speak freely here so it's there's no like sales pitch there's no like um formalized phrasing around this it's it's really allowing you to take a c-sharp program and make it very very um uh succinct right so you have webid application type uh c-sharp has implicit usings uh so now with with this it's literally available here so we've got webapplication.create given the implicit args from the program and then we have an app so within one line we've got an app and then we can walk up to that app and say map get so this is mapping the forward slash route so just an empty route to the get request that would return hello world in plain text and you can run that so this in three lines of code you're literally having a full hello world uh application um so it's i i think it's pretty uh pretty amazing now david let me ask you a question about that i don't want to give too much away i assume nick will get into this but i think what you just showed us is you know what we would have seen in the past in the file combined with pieces in the startup.cs file is that correct yeah it's very very much uh correct so like i think part of the evolution was you know coming from like owen katana not a lot of people really talk about that much anymore but there was startup and very you know common nomenclature that was evolved over time where there's these different configurations and configuring services and your di and all that stuff and it was kind of separated you had your program which is your entry point and then you had your startup which would kind of delegate out to all those different configuration bits and now um you can kind of like i said rapidly prototype out things and evolve you can still do controllers you can still do all the different things that you would want but this is a way to kind of i think quickly start expressing your intent and i mean there's a lot more in this uh this markdown file so i recommend spending some time going through it uh it's it's a very very great introduction to um you know how to do it and how you know kind of where to start but i think just you know avoid stealing any more thunder from nick we should just do the hallway track i think so too all right nick so i don't know if you can tell nick but like the the audience is is so jazzed that that we have you it's like it's like we've got an internet celebrity on um on our stream he's like yeah i know let's hope we don't screw this up or me for that matter nick have you considered changing your first name to scott that's my first question i had that's how you become like a very high profile person in microsoft uh so yeah i might do that so should we just jump into the biome great so this is very demo heavy i don't want to do slides or anything because i think the beauty of minimal apis is that i can show you what it is and you can completely understand um how you can make an api and actually uh david's these like three lines of code was my initial demo so i oh come on how to do that run yeah yeah yeah i just i need to show you how it um it all comes together just something i want to say in the very beginning uh because i'm i'm literally like all day i'm looking at feedback from different places in the community twitter our discord server i just want to say that this video this appearance here is dedicated to brainiac 5 from the cshop discord server who's a huge fan of minimal apis so let's start with the first thing which is the intro right so i'm going to go ahead here and create a new project and i'm not going to do any web api or anything i'm just going to go and create a console app with the.net 6 um well console app template so let's create a simple minimal api here so let's go to synchro and please let me know if you're gonna see this font uh which i hope you sure can so you know i i just have a question i'm looking at the icon there so um this is uh this is writer i guess correct yeah because i've never used writer oh okay yeah this is writer and it's a bit behind in visual studio 2022 preview and that's why you see this red squiggly lines here i'm gonna explain what it is i have a sort of like a story to tell uh but some of the features are not fully supported yet i'm gonna let you know which ones there are but yeah so let's go and create a console app nothing fancy no web no nothing and this is a new template now what i want to do is i want to go into the cs profile and the only thing i'm going to change is instead of doing microsoft.net.sdk we're gonna go and do dot web here at the end that's it so at this point i have two things the cs approach for example this error here cs pro and program.cs and then here's where i'm doing the app equals webapplication.create and then here's where we're going to wire up our minimal api endpoints in my case is the map get and i'm going to do hello world and then here comes the lambda and hello world there you go and that's it now we can simply do app.run and with these two files and i haven't added anything fancy here just that i can go ahead and run this api and then i'm going to use postman for the requests i'm going to run in this video so i've repaired some collections this is the api running here and you can see i'm getting not found because this is customers and it should be hello world there you go oh we applaud hello world we did it okay so so let me let me just for a point of clarification there's exactly two artifacts so far right there's the cs proj which has um basically that one change that you you added um and then there's the program.cs and you're just doing a uh i forget what they call it what's what's the term for program.cs that's not a class file that's a top level statement thank you so so there's very much so the reason why we can do that and the way i like to describe it i grew up watching power rangers so the thing i know that's comes together is like voltron so to me minimal apis are like the voltron of dot net six because you have top level statements from dot net uh five slash c sharp nine uh implicit and global using statements inferred lambda types attributes and lambdas and a few new dotnet six apis that make this possible so this all comes together and this and the interesting thing about this is that to be able to have for example attributes here from what i understand was a requirement for minimal apis to be a thing so she shop became better and supports this because we needed to have this programming model which is very interesting to me because now.net makes c-sharp better and c-sharp makes dot-net better i think we've seen lots of examples of that through the year right or through the years as c-sharp has evolved in the open alongside.net yeah i'm sorry i interrupted you no i was just going to ask if i could be the head sure voltron i think either damien or fowler will be that yeah or we can be we can be the legs okay you can be a toe your name's not scott cam it's too early for that i had no idea what you were talking about so and and here's an interesting thing because david you said something that i find very interesting you said that this is maybe for prototyping or rapid prototyping and i agree but here's where it becomes very interesting to me this is also a new entry level to asp.net core so you no longer have to create a new web api and see this eye logger being injected from the controller and where is it coming from and where is this controller being you know nude up i i am searching for a new like weather forecast controller i can't find it anywhere so i'll when i go to the learning curve like last thing i have i run a very interesting experiment that i want to share with you if we have time with a few graduates in that i work with but maybe for a different story now this is just like the bare bones but i want to compare that with effectively the three different ways you can build an api in dot net six so we have first the old way and what i've done here is i've literally took the dot net five web api template and i've updated uh the api to dot net six which means we now have file scope namespaces here so we don't have this extra intendation level but the rest is the same and we still have the startup.cs none of that is taken away this is still all there and this is supported model and people are worried you know do i have to now only use minimal apis and not use controllers well if i'm going to save microsoft if.net of the dotnet team wanted to do that it would break a total approximation of a hundred percent of all software so you you you aren't really losing that uh that's still gonna be there you can still do do that thing um you know the templates have changed a bit but the templating software.net new you can use it and make your own templates totally totally fine now the new web api looks more like this you do not have the startup.cs anymore and now you have these sections you have the builder to build section which is where you're going to register your services so imagine that as your configure services method if we go back to the uh old way of doing things and then you have the uh build to run which is the similar middleware approach that's all there is to it now instead of being in the configure method it is here that's it the rest is the same you still have controllers and in this case it looks the same as previously now if i was to this is still not minimal apis by the way this is just using top level statements and all those goodies to trim a lot of what people call fat what some other people call structure with startup.cs whether you like it or you don't like it you now have the choice to not have it there it's great now i want to go to the new way of doing this same weather app and i'm going to show you how it would look like as a minimal api so this is my take of structuring this a little bit but you still have your swagger gen you still have your authorization stuff and now you also have this map weather endpoints extension method and if i go here i created this this is where i've mapped that endpoint so this could totally be here but minimal apis doesn't mean everything should be in one file it means that you can start there and then you can give your own structure because you can technically do the same with the controller-based approach you can have everything in a single file but you wouldn't do that you would structure it so this is how it would look like very simple very clean very minimal and i don't know what you think this looks i i do like i do like this take on it because it kind of uh it's like a basically echoing the fact that you can evolve and grow right so it's you you prototype out like you've got this minimal api laid out and then from there you can structure it however you want so you decided to kind of re-implement this using extension methods on the web application type and it's very very clear what your intent is here and this is basically representing what would have been in your controller otherwise right and it's actually i have a full folder for here with three different ways of structuring this just because i wanna i wanna hammer the point home that we should be happy that this is a thing and not angry because i've seen anger as well because now you have the choice to structure things the way you want you want to go with controllers does that make sense to you fine i've worked with software that the only thing the controller does is called a mediator.send method and now i can actually remove that thing completely add an attribute to my handler do assembly scanning and trim that all together we'll see those examples as i go forward but i want to show you these three comparisons because it's important to understand what minimal apis are now this minimal apis thing this program.cs that has the weather endpoints you can totally have controllers as well in that project so you can have the minimal approach and the controller approach called having the same project however if you do use controllers and minimal apis the controller side of things because controllers come with a lot more like model binding and filters and model state and all that it they perform worse and now you might say how worth great question me so let me show you this uh performance test project that i have i have a project here and this project is using n bomber it is a performance testing software that will like externally hit your api the way you configure it and you can see how much traffic it can handle request per second request total traffic transfer and all that it's great written is in that shop and it has also a c-sharp helper package it looks like this what i want to do is i'm going to run all three of these apis so i'm going to run the old web api the new web api just so you know they all run in dot net six so we shouldn't see a difference just on the dot net version and then the minimal api now what i really hope is that the let me just close that is that my cpu doesn't go anywhere because i'm gonna hit it with 10 users which i think is threads behind the scenes um let's just run our apis because i'm not running them but never run c release and they should all be in release mode so you are running you are not running clearly why oh because i'm running i'm running the minimal api the original one let me just delete that so you are running you are also running you are also running and now with all these three i'm going to run three different tests at the same time for a minute with a warm-up period of five seconds should be enough to just get the jitter and everything running and then i'm gonna hit with um ten threads for one minute and while i'm doing that i'm we can actually pull some comments if we have any uh but let me go ahead and do that now so i'm going to go here and do a dot net run c release so and bomber will start doing its thing and while this is running feel free to yeah there are some questions we had an individual asking specifically what is a swagger swagger is well good question so swagger is a way to expose your api through the open api standard that's the best way i can describe it and i can't show you now because this is running but you can then go ahead and call an endpoint in your api and you can see all your endpoints listed you can specify the contract that it's accepting or it's returning you can make calls as well you can use the maybe authentication key to make a request straight from swagger and it's a great way to just document your api publicly and also interface with it and it's pretty standard for every api to have something along those lines grpc is using protofiles though so you shouldn't expect it there so while that's going i i do have a question you mentioned like controllers come along with model binders and all that and you know this far thus far all we've really looked at is like the http get scenario which you know doesn't really uh involve model binders when we go to http post and put and other http verbs like that where model binding might be a thing what do we do so we still have model binding we don't really have the model state object invalidation and everything that comes with that right out of the get-go um damian edwards actually wrote i think a minimal validation or mini validation package that brings the same flavor and looks that they're required and all those attributes and does all the validation but you're gonna have to write that yourself i'm gonna i have a section on that so let's just put that in on that point and look at the results because they're back now so what i want to look at is this thing here so first the old api still controllers 19 000 requests per second running for a minute and 19.4 000 here for the new one so the new web api and the old api both using controllers didn't really see any difference yes this is a bit faster but it could be within margin of error maybe a better core picked up those requests now if i go to minimal apis this is now if you compare it with this which again within imagine of error from 19 000 to 21 000 this is not negligible if you have maybe a kubernetes cluster and you're running 10 instances of your api now i need to run one less instance that something else can kind of use to have the same throughput so we are seeing in realistic scenarios in my results 8 to 12 better performance on minimal apis um and that's nothing to sneeze at especially if you're really working at scale uh it might be negligible for some people and maybe the value of having a toilet in the project is good enough but it's definitely something that's very attractive to me and here's where i think the value proposition becomes interesting you have people who want to pick up dot net c sharp and make an api jumping right in and using minimal apis because they're very easy to use then you have the middle ground where people are like very business focused maybe bigger applications not necessarily like you know micro services where the the vertical slice is just you know that customers api that payments api or whatever but it's a bit wider and they might want to use controllers but then you have people using controllers on a micro service level that this performance benefit is very attractive to me i know it's very attractive to me so it's interesting that starting with minimal apis is a great plan work with controllers in the middle area is also great or minimal apis if you want to structure them in some way but it's also very attractive for the high end to go back to minimal apis because of that performance now you can't necessarily take a controller based solution and just convert it into minimal apis because you don't have a few things i want to just list what you don't have which is you don't have filter support you don't have support for model binding with the imodel binder provider or the i model binder sorry you don't have the built-in support for validation with the model validator support for all data json patch all that you do not have so you'd have to implement something yourself and this is where i want to go unless you have something you want to add on the performance side of things to the next thing i just wanted to point out so uh aside from the performance thing you had said you know eight to twelve percent more performant than the traditional controllers approach i think this also brings this additional benefit of um appealing to a broader audience uh dot net carries with it this reputation of being an enterprise grade bloated framework and that if you want to create something like a web api file new project results in a yard sale you've got files everywhere you compare this to other developer ecosystems out there php with lumen node.js with expressjs and python with django and the list goes on and on and you look at their boilerplate that's scaffolded to do something similar it's very very minimal and so i i really view this movement as sort of what we saw with razer pages versus mvc where we were reducing the the concept count thereby appealing to a broader audience but i and that that point about you know like what we did with nbc um it reminds me of that in that you know controllers aren't going away controllers are still there if you want them right yeah so i think there's a a couple of questions i want to address first one how do you use authorization and model validation with minimal apis so we're going to show you validation right in a second authorization stays the same you still do your ad authorization ad authentication and then the use methods on the middleware that is still all the same um let's say you wanted to allow anonymous for one of those endpoints you can totally go here and you can now have attributes that's not how you create an attribute attributes here so you can totally have an allow anonymous attribute on the lambda to do that but you can also have the let me just rewrite that change yep you can probably have the allow anonymous extension method here as well so and this goes for other things for example if you want swagger to have details on how your api accepts data and returns data you can have things like produces and have the the status code for example producer 200 and returns um an innumerable of um sorry that's a type so a type of innumerable of weather forecast there you go and this will be reflected later in your open api file so you still have all the power that you had before it's just either a different way to do it or you now have to use the attributes on the on the handle on the delegate level but other than that it's still there and a lot of the extension methods are actually the same so if you go back to program real quick for example like some of the uh extension methods that existed uh on my service collection are still there right they're the same ones in fact so it's yeah yeah so let's talk about validation for a second now that was something i did late last night because i just came up with this idea that can i do this because like i said filters aren't really supported in in this format now if david or damian are watching this or watch this and this is not something you want people to do sorry the api allows this so i'm going to do it anyway uh but let's say we have this this minimal api here where we i'm using fluent valid data i don't know if you're familiar with validator it's a great nuget package for doing validation against an object what many people might have is you might have your api contract validation to make sure that the the value is not empty or you don't exceed some characters but usually what you have is a level deeper you take the data you map it into a domain request maybe and then you have fluent validation validate against that and i was trying to figure out how i can do this with minimal apis because sure you can go here in the customer endpoints and this is just another way you can structure it and you can have um a map post method which is what cam mentioned and i have a create customer with validation let me be aware of where our faces are great so um what i'm doing here is you can totally inject services the same way you would on a controller but now you have it on the delegate on the handler level you no longer need to have it you know all the way up here on the actual class which also makes it quite easier to unit test as well because you only have to mock the thing that you're testing on that handler and then the customer for example here this is coming from the request body so that is taken and then converted into an object and then the i validator is coming from di as well this is coming from fluent validator if you want to be explicit about where these things are coming you can have the from services or the from body attributes exactly same we had before this is not new but you can totally have them there but what's interesting is net or minimal apis on startup they will look at this and be like oh i think actually i know this is coming from the service collection because i have something with that type there and maybe go here and say i don't have this in my service collection this must be something coming from the body and this is on a startup so you don't have to worry about performance that things are being resolved dynamically uh we do have a question real quick here so why do some endpoints start with the forward slash and others do not i don't think they all the ones here start with that but i think i'm showing if you saw that in other files i might be showing early signs of bipolar disorder both will work though so don't worry about this you do you so let's go back to let's create uh with validation right so let's actually run this api uh debug it yeah and i'm gonna debug it now you might be looking at this i did not uh twice in the same video or stream i did not shut down the apis let's run this again um yep this is running so what i'm gonna go is i'm gonna i'm gonna go and do is this is not running the right thing live shows let's run this now again this is where you would edit it out in your youtube yeah editing this is so much easier so yeah let's go ahead and create a customer in this api and again we're talking minimal apis but you don't see any endpoints in a single file or anything this is still you know structured we're mapping our endpoints we have the services here for the customer serv endpoints and i just defined them in this map extension method and that's it i don't have to have them in a single file now i'm going to go here i'm going to go to postman and pull up the create customer endpoint and i have a full name here this is what my object should look like and i'm gonna send a request so i'm hitting that breakpoint and if i f10 you can see by the way that i have my customer with my name here and i randomly sorry a randomly generated good and then i'm going to validate that it's valid so i'm going to create it and then return the request and you see that we have the response pack with the created object and if i check the the headers as well over here i'm getting the the location as well so i know where that resource was created very nice now and if i wanted to you know list all endpoints so your customers i can do that here now this approach since we don't have the model state means that we have to technically have this i validator injected on every single one of those endpoints which isn't great what i like is generics i like the fact that c-sharp can be like take this customer type and then go in the background and do something but i don't really like having to use reflection on these types of things because if you're working on a high throughput scenario and then i have to use reflection that might make my ap depending on the usage make my api slower than the controllers approach then i might as well go and do controllers instead so how do i make this blazing fast okay this is what i came up with david damien if you're watching this i'm so sorry so here is i'm not going to show you this yet here's how you would do this i'm going to remove that and i'm going to say create customer i love that you keep apologizing to them i wanted to do it yesterday but it was late for me and i wouldn't get the response so what i have is a create customer uh version but without any validation so how do i make this generic right well here's where freedom of choice comes into the picture and this by the way isn't as elegant not even with controllers i don't think in my opinion anyway so we're going to go here and what i want to do is i want to say this is the thing i want to have a validator for so i'm going to say dot with validator customer this is not amazing such keys now the code behind this i don't know if it's as chess case but before i show you the code i'm going to run this this is again this is a wrong api just stop that and debug this over here here we go so let's go and create a customer and if i want to just create a customer uh the customer was created successfully from that new endpoint and if i want to create one that doesn't have a full name because i should show you my customer validator has two rules rule for the guide it cannot be empty and rule for the full name it cannot be empty so if i do that this gonna go boom uh full name must not be empty now i'm just using fluent validators um error object in this case you shouldn't really do that you should have your own like standardized api error contract and then version that and map to that but i am lazy so let's go ahead and show you how this is possible so validator allows you to or what later they you can extend the the route builder which is what all those other things like the uh with metadata or with tags or with display name and all that can have but one thing that i noticed was was exposed was the request delegate which is what is handling effectively the request so what i'm doing here is i am adding to the builder um well an extra convention which is boxing the old request delegate and then not boxing sorry it's creating a closure with the old request delegate and then i'm reassigning it to pick up dynamically using the the type provided in the validator the valid data from di and then process this properly it's going to do a bit of buffering and rewinding on the body because it reads it twice but it works and this thing like this sort of thing they're not going to like it but i know they're not going to like it but they allow it i'm going to use it it's amazing you know this type of thing the moment this actually worked i was like just like so excited because you know we can have filters now with this approach is it the proper way of doing this no have i benchmarked this no but i can a choice i i think this is going to inspire them to to you know create a feature there might already be something in the works actually for something similar to this so this is uh this is interesting interesting i i think the biggest concern is going to be the the rewinding and the re-reading of the the request body right that's going to be a performance consideration you know yeah twofold right away right but then anything that's being validated but i do uh i do like the approach um i think it's it's cool yeah i mean but but in any case it's it's it comes back to that freedom thing you know even the structure you don't have to have this in a single file you can structure it any way you want and unless people have any questions i can go to the structuring in more detail and show you a few other ways you can actually structure your minimal apis can i ask a question real quick oh yeah so one thing i noticed here is first of all i really like the the customer endpoints um it's actually an abstraction thing that i started doing with my minimal apis as well so it's it's nice to kind of have other developers who are in the wild doing having the same train of thought right encapsulating your common things over into its own file and then um but you you have internal here for some of these things and i'm assuming that's for unit testing correct okay otherwise those could have been private right because it's awesome absolutely absolutely but but because you want to be able to use what so there's a debate whether you should be unit testing your your handlers in the same way there's a debate whether you should be unit testing your controller action method right now i'm not going to get into well actually i am going to get into that but in a couple of uh well folders here um some people want to do that some people don't i see the value if you want to validate the mapping if you go from a domain object to an api contract and make sure that that's all mapped fine and it's a very like quick feedback loop which i like but if i want to do a more like you know not end to end but like system test about this type of thing i might just use the waff or web application factory which is great for that type of thing but it isn't unit testing that is more of a narrow integration testing we did have about a bazillion of our live viewers has you know consistently asked for the source code uh they they want to look at this they want to play with it they want to see it so i'm assuming that you will share that yeah i'm going to so if you go on github and search for nick chapstos or google you'll find me i'm gonna upload all that label.net show minimal apis the reason why i did not do that is i started this repo and i have some git messages i don't want to have public so i'm gonna do a new thing well see well i i am very proud of my commit history and if there's foul language in there i will uh share my frustrations that way so [Laughter] if you would direct your attention to line 26 here and the customer endpoint um is there a reason why you chose to return i result as opposed to i action result great question you cannot return i action result well technically you can you know what let's just try it i know what's going to happen because i was curious as well let's not waste time basically you you're gonna get the full object i action result one level higher you won't get like the status code being mapped properly the body being mapped properly or the headers um the new abstraction if you wanna do like a similar iac result experience is our result the problem with this and that's not really nice and i talked about this is that every single implementation of i result is let's give ryder a chance to weld this it's internal meaning i can't really hardcast it to anything if i want to unit test it so that's not nice again do you want to unit test your controllers you might not i think there's a use case i think we shouldn't really have to deal with internal things and there's ways around it as well you kind of have to write your own approach um or convert it to another object and then remap it to something you have access to um but that's why the new thing is our results and if you want to access the same like okay or not found methods you want to go and use the results dot class which um contains all of them if i do for example results that separate bytes challenge you you still have all of them here and then we do have a question right away someone's asking whether or not async endpoints will change the return type i'm assuming that it's eye result regardless yes yeah it's i mean you can still have like um a task of our results to return so this is still actual code uh you'd have to have a weight keyword somewhere it's probably complaining about i think it's something else but i can only be used you can probably have that though let me just quickly go up and show you i don't really want to debug by this is coming out but you can have a nice saying something that returns right low well here and this that would work all work could you return like dynamic no never mind just move on i think that's the recommended way to do it this is a joke in case someone doesn't right right right we're talking about no js we're picking on you no yeah don't try that at home yeah no dynamic so let's talk about structure a bit because that that is one of the most common things i see around people complaining that now you have to have everything in a single file um you don't in the same way you don't have your controllers in a single file you can structure everything you want the difference is you know choose how you can structure it it's completely up to you um so let's go to the structuring project and i have three different projects here i've actually talked about one of them in a video but i'm gonna recap all three of them um so first one you have this more like vertical slice type of thing where we have like a customers uh folder and my program.cs looks like this this is very similar to what i had before i have and add customers oh sorry not customer services don't pick a file with node.js that is true anyway add customer services and then map customer services and then you drive this with extension methods it's kind of the same thing as before you have you're extending the web application which has all the map get post and all those methods and then you split things uh by things i mean your endpoints with individual methods and this all works fine this is basically the most simple and basic way to structure your minimal api in my opinion now we're going to take this a step further and we're going to go to the scanning project here and what i have here is this simple program.cs we no longer have customer specific this is still the same api by the way still customers we don't have any customer specific stuff but we do have an ad endpoint definitions with a type here which is used for assembly scanning i will explain what that is in a second and then the use endpoint definitions extension method and that's it now you can keep adding what i call endpoint definitions and that's all you need to do you just create a new class here and you implement the i endpoint definition clause and then something magically will come in and scan your assembly the assembly containing whatever type you specify here and it's going to register things with a right lifetimes for example you know i have the define endpoint methods here that's going to get invoked dynamically and then i have all my endpoints here you can see they're not static anymore no extension methods this works in the same way and i have my swagger endpoint definition here where i just split my define endpoints and my define services extension methods here or methods for that matter and i can show you what's in the endpoint definition extension method effectively i am scanning for anything implementing the i endpoint definition interface and then i'm instantiating it and then i'm calling the define services method adding the thing as a singleton um in my case as a singleton ndi the the full collection and then i'm also mapping the the define endpoints so i'm adding this in di to be picked up in the uh use and point definition call here and that's it if i want to add more like i don't know a payment endpoint definition i can just do that payments and endpoint definition i can have an an i endpoint definition thing implement the two methods that i have to define services define endpoints and that's it i don't have to do anything else you can see here how uh github call file that is trying to suggest things i'm gonna ignore that um but that's it that's another way you can structure your apis and now going back to what i said before about mediator you can also because a very common scenario is you have your controller and your controller is mapping from an api contract to like a domain level request and then you're shooting that to a mediator handler to do the processing and return it back you like what about this and again this can be also simplified but i want to show you the more explicit way of doing this you still have your imediator here and you still call your mediator.send this isn't in its own file it could be but in this case i'm going for a more minimal approach real quick question yeah maybe it's just the zoom level but the rendering of the goes to operator the equal greater than it looks like it's a single line for me uh which one the equal rather than being an equal sign is that an equal sign can you zoom in a little bit ah there it is okay it looks like it was just a single arrow and i was like okay what's this new operator timeout pump the brakes this ain't this ain't java i can make it do that single operator if you wanted to use the pointer but it feels like there's a joke about c sharp there uh so yeah this you know a very other very simple way to do that and then all you have to do is implement the handler and you have your request here mapped from the body and you do your your processing these approaches all work this is just three ways to do your structuring without having to follow a very specific way if you want to follow the very specific way it's there but you have that choice i i question so i know that you're being kind of you know you're casting a wide net here you're going out to many developers and you have the advantage of having a very popular youtube channel so you solicit a lot of community feedback i'm curious though what's your opinion what what is your preferred go-to way what are you going to do in production and why can i add more today i would say what's what's your preferred approach when performance really matters because i look at this scanning approach that you showed and i wonder what's the performance impact of doing something like that just to clarify before i dive into anything this just reflects my opinion and does not represent my employer so huge disclaimer here so what nick says that scanning approach doesn't really degrade the performance in any way because it happens on startup so the registration of the endpoint would happen the same way as if you did it uh manually so the right it's still a performance from the aspect of startup so it takes a little bit longer for your app to be ready to serve requests yes yeah yeah that that is there that's that's true but nothing that would go into the seconds level just so we're on the same page um what i would do if i all i cared was performance is i would go with the extension method approach so i would explain i would be explicit about everything because you might ordering might matter as well especially around middleware um so and i want people to like exactly look at the program.css and know what's what and don't have to guess of oh this thing is loaded from a package or something um but me too that's probably what i would do so it's good to be here now but i've seen people use magic quite a bit and i'm going to show you how you can do magic for minimal apis because like you said it's a it's a it's a casting a wide net now i would also use minimal apis and that's my personal opinion because that huge 10 to 12 performance at the scale i am personally looking at is nothing to sneeze at like i said this can be um oh we're getting rated this can be um literally a new instance of your application not needed to be run meaning less thing to run for the same performance uh which is great and i'm i totally fall under i think i fall under all three categories i have code in controllers that i would never move from controllers because it's fine i don't need to take the risk of moving to minimal apis i have prototypes i want to do that i'm definitely going to go with minimal api is very like one file approach and then i have things where it might worth taking a look at getting that performance advantage and to me that's the most appealing thing other than the programming model but i also like the programming model because on a more personal level that it's not like performance performance performance it allows me to express myself better as an engineer and i like that that's where i stand and thanks for the raid that's awesome uh so we're getting close to time so what else do you have to show here you got you got testing you got learning curve you got other things yeah i mean we're only in project four of six so i think we just scratched the surface i'm totally bad at timing things if you want to wrap it up we can wrap it up no no no let's keep going let's keep going cool so let's go with testing so what you might have seen uh especially if you're following um damien and his playground uh github repo is this type of testing here where you have i think some people call them unit test for minimal apis to me like i've mentioned before these are integration tests either narrow or broad i'm going to explain the two terms but minimal apis can work in the same way that you can have an application factory for your this is where i said that writer didn't catch up actually normally you would have an application factory with a startup.cs here instead of program but we no longer have program sorry we no longer have startup so now we have uh programs yeah that's c-sharp c-sharp i love that you have to rebrand it um and you'd have something like that here the the test application factory and then what this will do behind the sims is effectively create a full-blown api that doesn't really expose anything externally and what you get back is an http client that can in memory call that api only that thing and call it so if i wanted to do narrow testing integration testing which has mocks in it in my case i could do that using the class that you see here i have a delegate here the service override which allows me to dynamically override things on a test by test basis and by things i mean dependencies so assuming that this icustomer service is calling some database maybe it uses ef and a data context behind the scenes something we don't know but if all i want to do is have my arrange octa set and you know create a customer and then spin up the service and then use the http client and read the context and get the result back and validate that this would happen and in fact let me just debug this real quick so you can see how it works so let's close that and as you can see we have a new customer i'm using any substitute here to do the mocking so this looks very natural with extension methods this is my preferred way of doing it and then this app this application factory is what will be spun up when i step over this create client method and now i have this http client that only that thing can call this api that is now running a full api and if i did not mock anything here by the way to this container it would actually call the actual database so this is great for integration tests as well uh or what i call broad integration tests in this i'm going to show you in a second so would you recommend connecting to the production server obviously i think that's how you should do it and if you have anything running locally like shut it down as well just to make sure it doesn't it doesn't hit that um and then you know this request this response text is coming from that calls we just made and we validate our status code and the the actual result and i'm using fluent accessions here to do the the accession now if you want to go with a more broad approach same thing but without the without the mocking of the of the of the service the i customer service um now that's what in my opinion falls under again integration testing if you wanted unit testing things are a bit more interesting because like i said this eye result thing that you might be returning doesn't really expose its concrete return types you might not want to do any accessions on those types that's totally up to you to do but if you do want to comparing it to controllers you no longer have the choice so if you're returning let me go back here if you're returning this thing which is like the list and always returns like um 200 no matter whether you have items in the list or not um then you can assert against that this is what those unit tests are actually doing now i have shown how you can do the eye result thing but it goes into ground that i'm not really happy with touching which is reflection and maybe you don't want to do that but if you wanted to do that type of a session you would look at something like results that should oh i haven't implemented any tests anyway if you want to access those objects that we talked about earlier you'd have to instantiate them in a in a in a reflection way a reflection approach um now i know that damian said that he's working on something that will allow this to be possible without using reflection so maybe keep an eye out for that but for now know that it's a bit tricky to do unit testing if you're returning a result and you really care you might not need to but i have to put it out there and that's what i have interesting all right i'm very conscious of time that's why i keep an eye on no so don't we have a couple of minutes um guys should we dig up a couple of uh viewer questions real quick yeah let's go ahead what do we have here um lots of comments we have the viewers are all excited about um about minimal abs here's a good question um is it possible to scaffold minimal apis like what what exists out there for scaffolding um or is it all just like are we all at like copy and paste stage here good question i haven't looked if there's anything added lately i think there is a new toggle you can enable minimal apis on the web api template writer doesn't have a checkbox for that but i think if you go on visual studio you have an option to create it using minimal apis you could use the the.net cli uh in addition and as i pointed out in the chat um if you're not happy with what's provided it's actually fairly easy to create your own custom project templates and if you subscribe to my channel i have a video for that next week um actually you know can you uh put your put a link to your channel up there let's make sure everybody has um knows where to find you and and your code because we had a lot of questions about this code i know you said earlier that it's not on your github yet but you're going to uh you're gonna commit it later and uh make it obvious so people can find it just follow me there and i will uh i will upload it awesome i pasted my youtube channel as well so if you want to subscribe there for more content what you did oh there it is look at it hey you're in the chat all right so um with that i want to thank our hundreds of viewers that we had this week um for watching the.net doc show uh and most of you i'm sure are new to the.net doc show you probably missed our intro i'll take this opportunity just to say we are a one-hour unscripted.net entertainment stream every monday at 11 o'clock central time us and we would love to see you again um you can check out our show recordings our upcoming topics and more at our website dotnetdocs.dev please join us next monday when we're going to have bruno garcia and joao gracie they're going to be talking about what are they going to be talking about uh nougat trends that's awesome um so uh nuget is is fun uh it's always a fun topic because there's a whole lot of moving pieces there that i never think about when i type net ad package right um so we look forward to seeing you then and uh until next time this has been the dot net doc show thanks everybody for joining bye friends [Music] so [Music] you
Info
Channel: dotNET
Views: 9,537
Rating: undefined out of 5
Keywords:
Id: HDinmuGYaIA
Channel Id: undefined
Length: 63min 10sec (3790 seconds)
Published: Mon Nov 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.