Going one step further in the same direction, i would turn namespaces "inside-out" for endpoints, requests and responses. Instead of having a general technical grouping of "endpoints", "requests" and "responses", i would create namespace per collection of single "endpoint + request + response". This way the request and response model is nearby the endpoint that uses it, instead of being in a "generic namespace" of "requests" or "responses". I've had great experiences with FastEndpoints. This nudges you to write beautifully structured APIs.
@@GigAHerZ64 It would end up that way, I agree. As soon as endpoints become more versatile, such as GET, POST, PUT, PATCH for every item, their corresponding request and response types would go along.
The problem that I find with this approach is that it's hard to reuse requests and responses this way. I know I could define a base request and then inherit from it to define 3 new identical requests, but it feels a bit unnecessary and bureaucratic. Perhaps some endpoints could just choose not to implement their own response or request, but you would still have to keep a separate response, request namespaces, at which point I feel like you may as well throw everything in them.
@@JanVerny I tend to reuse requests and responses through record composition, a technique common in functional programming, rather than through inheritance. It works exceptionally well, both in code and in documentation.
Thank you, Zoran! This video was incredibly helpful. Your clear explanations and practical examples made complex concepts easy to understand. I really appreciate the time and effort you put into creating this content. Keep up the great work!
This approach is by far the cleanest way to manage Minimal APIs. This reads as easy as a Swagger spec. Using this pattern, developers can see the why and what, then if required, dig into the how. I wonder how easy it would be to add support for inject of services like HttpContext and mocking?
Nice video. Personally, I would replace all the routing with a custom Attribute similar to how Controller Route Attributes work. It would reduce the amount of code needed to setup a route. You just tag the function with the route. But that’s more of a personal preference. I can understand why some people may want direct function calls.
Very nice approach, thanks for sharing 🤗 I used to move all endpoint building to a separate class, but this way it's not as clustered as it was with mine. It's obvious what happens, very well done
jó napot kívánok, I love your videos, especially the ones focussed on functional programming and DDD. Personally I prefer more to slice my application in verticals and domain concerns, in stead of technical separation like “endpoints”, “models”, “entities”, etc. I love to see clean `program.cs` files and the use of extension methods to achieve this! ❤ Please continue providing videos. A more theoretical one like, how to find entities, and when to decide to create a dedicated type in stead of a primitive would be greatly appreciated. Also, please consider applying to the CfP of Techorama Belgium again. It is open now, and as a crew member, I would love to see you there again!! 😉
Jó napot kívánok! Thank you for telling me for Techorama CfP, I see it was just opened yesterday. I will surely submit a couple of talks I have available now. Regarding the videos, there is a large topic I have in the queue about designing a model from scratch, including UI/endpoints and persistence. It will be a significant piece of work, but I reckon that many of my viewers are waiting for something like that.
Hello, thank you again for an amazing video. I'd like to understand something better however, that I never see to be addressed when talking about minimal APIs: What is the difference between the AppConfiguration file you created and the typical Startup file created in a non minimal API? What is the difference between the AuthorHandler and let's say an Author Controller in a non minimal API? I don't want to become a dinosaur, and I'd like to understand what is the point of a minimal API. So far, they only feel like something that just looks different, with no particular values added to them. It feels like nothing is gained from using them over the previous controller system. As I said I'd love to understand them more and enjoy your way of teaching, thank you again for all your videos.
I believe the most important difference for a Web developer has little with the way they program - endpoints are faster than controllers, and take up less resources on the Web server. However, there is an important consequence in the way we write code. Minimal APIs are based on functions they map, which sounds suspiciously similar to functional programming. My belief is that minimal APIs are lightweight and fast in the same way as functional compositions are. Hence the conclusion. If you organize your project in the functional style, then a minimal API will simultaneously be your first and your best choice.
I haven't really played with minimal APIs yet, in part because I still prefer the comfort of the full controllers approach. I'll have to remember this if I ever do, as that is a very neat trick.
Minimal APIs are the library of choice when designing functional models, for the way they are organized. They also add performance to heavily burdened Web applications.
Fantastic video! You left the video so close to being able to apply Vertical Slice Architecture! Just use a root folder Features, which contains Authors, Publishers, etc folders. Place only the relevant files in each. Increases cohesion and navigability.
I started my minimal journey this year, being assigned to ongoing project, and my first wtf moment was when I saw the one humongous file - 'how did we end up here again?'
@@marcobaccaro Controllers are object-oriented. Minimal APIs are functional. If your domain model is object-oriented, then controllers are easier to integrate with them. If your domain models are functional, then integrating them into controllers is nothing but a royal pain.
@@zoran-horvat Maybe I'm too averse to change but seem to gravitate towards a thin controller/service/repo architecture. Next time I have a green field project I will look into M-API again to see if the benefits outweigh the learning curve. Thank you for another amazing video :)
@lolyasuo1235 global usings and removing brackets on namespaces are a welcome addition, but sometimes it feels like the .NET team is making changes for the sake of change.
@@lolyasuo1235it would be cool to see a nice obvious example where Minimal APIs handily outperform their standard controller equivalents. I'm still so early on my learning journey.
Really interesting... I moved all my endpoints to static classes of logically grouped endpoints (don't call them controllers 😉) with the the MapGroup at the top of each. These static classes called UseAuthorEndpoint, UseBookEndpoint etc. each return the WebApplication for chaining. I've left the logic for each endpoint in the endpoint lambda, which leads to my question. Is there any benefit to separating out the logic into static methods once everything has been tidied into these separate files? Really love your work, My work day always starts with a calendar entry for revision that is usually one of your videos...
The hidden part of minimal APIs, which many programmers don't see, is that they are implemented as a functional library. With explicit static methods rather than lambdas, you retain all the functional tools that exist, primarily partial function application and monadic composition.
Not bad, but still not sufficient for me. I would use REPR pattern with minimal api endpoints with scanning (including groups/base groups etc.), so one endpoint per file - that contains all details about endpoint registration and endpoint executive.
My first thought at the beginning was that it would be a MediatR implementation, and this would be my approach if I would see such code. I'm glad that you proved me wrong - your way is much nicer. MediaR is ok and could do the job, but it will be too obvious and too mainstream compared to the level of quality of your channel. Thanks for the tip! Now, to the refactoring-mobile 😂
@@serviceengine I don't like adding more libraries when vanilla code gets me to what I wanted to accomplish. That says nothing bad about the MediatR, which I think is good.
@@zoran-horvat Probably not... in the past I've organized a minimal API project like you've shown but there were a bunch of methods that took many of the same dependencies, I was wondering if there was a better way
@@johnnyutah23 I say that because there is no duplication just because two methods accept the same dependency. The duplication might occur if they do the same thing, but the dependencies alone are not indicative of that.
Primarily the structure of a traditional OOP project. If you are used to object-oriented programming, then controllers are a natural choice, as everything in them is OO: from model binding, model validation, over actions, persistence, all the way to testing. If, however, your code structure is more functional, based on static functions and separation of data from behavior, then minimal APIs seem like a modern, fast, and composable solution for future projects.
@@shadowsir That's what I said in the video - if the model is large, minimal API is probably not the right tool for it. And vice versa. A limited, focused model, which only manages one domain concept, likely doesn't warrant the added complexity and weight of controllers.
Місяць тому+1
To be frank, this seems to me you just implemented a worse version of controllers.
If you start from the differences between minimal API and controllers, then you will quickly realize that it is not. Could it just be that you have developed a habit of writing controllers and now you cannot look away from them?
Місяць тому
@@zoran-horvat I know there are differences between the two approaches and both have their place. But what exactly did you gain by doing this refactoring exercise? Correct me if I'm wrong, but if you redo this with controllers you'll end up with the same number of classes, less code in both the controllers and Program.cs, and arguably an architecture that's more predictable/standard.
Nice video Zoran, although this is more a presentation on the Single Responsibility Principal and how to refactor code to achieve this. I would go even further and separate out the service configuration and endpoint configuration into separate methods/classes. Minimal API has been used as an excuse by lazy engineers to not implement SRP. And if anyone were to present the initial code to me for review in a PR, that PR would be very quickly refused.
@@John.Oliver That is correct about code review. The initial code, which I have seen quite a few times, is indicative of an irrational belief that minimal API is so small it doesn't require common programming.
That could be one of the next videos, depending on interest. I always do the vanilla approach first, because that is what the framework and the language offer.
Give me one valid point to use fancy things there out instead of traditional APIs which is the best way to go. They are so simple so there is no excuse. Why not to go? they are "fat"? I am going to get 29.9k RPS instead of 30.5k RPS (minimal APIs)? So What. And the minimal APIs are reinventing the traditional APIs so its waste of time.
The more I see these workarounds and tips surrounding minimal APIs the more I like the out-of-the-box simplicity and intuitiveness of good ol' controller classes. All this work and we end up with basically the same thing as there, except more obfuscated and bloated with mapping code and methods that used to be just [Route("foo")]
@@zoran-horvat I'm not sure what a functional controller would even be, but as far as I can tell all the routes in the video could be easily rewritten with the old controller approach? The whole set of handler classes with static methods and the required registrations in program.cs just seem like unnecessary code compared to having them intuitively separated by controller classes and having mappings defined right next to the controller method (and the code using them).
I kinda disagrez about "Minimal API m" being used for "smaller projects" A well structured minimal api project is faster and also is more explicit. Even microsoft themselves only show it in one file on the doc just for convenience, that's not really how a bigger project would do it. And i bet bigger projects could still use Minimal api, or maybe FastEndpoint. I wouldn't go back to controllers personally.
@@WDGKuurama There is one hidden gem in them, which many people never saw. Unlike controllers, which are object-oriented, minimal APIs are functional. If you can organize your project the way functional projects are organized, then minimal API will be the more convenient form for the Web layer. I plan a video about that in the near future.
@@notoriouslycuriouswombat Can you identify what is messy, precisely? I didn't change a single line of code during the refactoring, and yet, the final implementation I wouldn't call messy.
@@Robert-yw5ms Well, no. That is a complete implementation of just a few endpoints with nothing missing - especially validation and the proper construction of error responses. There is nothing specifically wrong there.
strangely satisfying when you watch a video and go "oh I already do this! cool!"
You are right. Minimal APIs can get out of hand so quickly that I don't expect to see a programmer who didn't do something about it already.
Your way of explaining is very wonderful and so is your way of speaking. You are literally the godfather of programming.
The way you speak is really really special, it just captures. And did I even see on UA-cam any more deep C# videos? I don't think so
Going one step further in the same direction, i would turn namespaces "inside-out" for endpoints, requests and responses.
Instead of having a general technical grouping of "endpoints", "requests" and "responses", i would create namespace per collection of single "endpoint + request + response". This way the request and response model is nearby the endpoint that uses it, instead of being in a "generic namespace" of "requests" or "responses".
I've had great experiences with FastEndpoints. This nudges you to write beautifully structured APIs.
@@GigAHerZ64 It would end up that way, I agree. As soon as endpoints become more versatile, such as GET, POST, PUT, PATCH for every item, their corresponding request and response types would go along.
The problem that I find with this approach is that it's hard to reuse requests and responses this way. I know I could define a base request and then inherit from it to define 3 new identical requests, but it feels a bit unnecessary and bureaucratic. Perhaps some endpoints could just choose not to implement their own response or request, but you would still have to keep a separate response, request namespaces, at which point I feel like you may as well throw everything in them.
@@JanVerny I tend to reuse requests and responses through record composition, a technique common in functional programming, rather than through inheritance. It works exceptionally well, both in code and in documentation.
@zoran-horvat do I hear a new video title???
@@zoran-horvat Id be very much interested in that as well
The way you talks keeps me watching until the end! Education + Entertainment = Happy Coding
Thank you, Zoran! This video was incredibly helpful. Your clear explanations and practical examples made complex concepts easy to understand. I really appreciate the time and effort you put into creating this content. Keep up the great work!
This approach is by far the cleanest way to manage Minimal APIs. This reads as easy as a Swagger spec. Using this pattern, developers can see the why and what, then if required, dig into the how. I wonder how easy it would be to add support for inject of services like HttpContext and mocking?
Nice video.
Personally, I would replace all the routing with a custom Attribute similar to how Controller Route Attributes work. It would reduce the amount of code needed to setup a route. You just tag the function with the route.
But that’s more of a personal preference. I can understand why some people may want direct function calls.
Great movie! In 9:50 you could have pressed Ctrl + R, Ctrl + G to remove unneeded using-s.
I always do, but here I wanted to make it last longer, for the feeling of deleting it with my bare hands :)
@@zoran-horvat :)
Great Video! Always satisfying to clean something up. I would prefer a vertical structure along the usw cases though
Very nice approach, thanks for sharing 🤗
I used to move all endpoint building to a separate class, but this way it's not as clustered as it was with mine. It's obvious what happens, very well done
Excellent tutorial Zoran!
Another piece of gold from you!
Wow, that's the cleanest program.cs I've ever seen!
jó napot kívánok, I love your videos, especially the ones focussed on functional programming and DDD. Personally I prefer more to slice my application in verticals and domain concerns, in stead of technical separation like “endpoints”, “models”, “entities”, etc. I love to see clean `program.cs` files and the use of extension methods to achieve this! ❤ Please continue providing videos. A more theoretical one like, how to find entities, and when to decide to create a dedicated type in stead of a primitive would be greatly appreciated. Also, please consider applying to the CfP of Techorama Belgium again. It is open now, and as a crew member, I would love to see you there again!! 😉
Jó napot kívánok!
Thank you for telling me for Techorama CfP, I see it was just opened yesterday. I will surely submit a couple of talks I have available now.
Regarding the videos, there is a large topic I have in the queue about designing a model from scratch, including UI/endpoints and persistence. It will be a significant piece of work, but I reckon that many of my viewers are waiting for something like that.
Extra nice work!
Hello, thank you again for an amazing video. I'd like to understand something better however, that I never see to be addressed when talking about minimal APIs:
What is the difference between the AppConfiguration file you created and the typical Startup file created in a non minimal API?
What is the difference between the AuthorHandler and let's say an Author Controller in a non minimal API?
I don't want to become a dinosaur, and I'd like to understand what is the point of a minimal API.
So far, they only feel like something that just looks different, with no particular values added to them.
It feels like nothing is gained from using them over the previous controller system.
As I said I'd love to understand them more and enjoy your way of teaching, thank you again for all your videos.
I believe the most important difference for a Web developer has little with the way they program - endpoints are faster than controllers, and take up less resources on the Web server.
However, there is an important consequence in the way we write code. Minimal APIs are based on functions they map, which sounds suspiciously similar to functional programming. My belief is that minimal APIs are lightweight and fast in the same way as functional compositions are.
Hence the conclusion. If you organize your project in the functional style, then a minimal API will simultaneously be your first and your best choice.
I haven't really played with minimal APIs yet, in part because I still prefer the comfort of the full controllers approach.
I'll have to remember this if I ever do, as that is a very neat trick.
Minimal APIs are the library of choice when designing functional models, for the way they are organized. They also add performance to heavily burdened Web applications.
@@zoran-horvat Correct, although it should not by used as an excuse for not implementing out SRP.
Science that is advanced enough will be mistaken to be magic. This is magic without a doubt. The magic of abstraction.
I think of minimal API as a routing/mapping mechanism. Every method is only one line to call a method on a domain service.
Excellent video. Thanks
Very good solution
0:34 I thought I would hear "One File to rule them all" lol
Fantastic video! You left the video so close to being able to apply Vertical Slice Architecture!
Just use a root folder Features, which contains Authors, Publishers, etc folders. Place only the relevant files in each.
Increases cohesion and navigability.
@@unexpectedkAs That shows how closely related all those ideas are.
Very nice topic. Thanks
I started my minimal journey this year, being assigned to ongoing project, and my first wtf moment was when I saw the one humongous file - 'how did we end up here again?'
@@prec6383 I had that moment once, too.
Dear Mr. Zoran,
I hope my comment finds you well.
Please keep going with such great videos.
Yours 🎉
This cleanup and organization are so necessary that I never understood why minimum API was used; I just stuck with the classic way and controllers.
@@marcobaccaro Controllers are object-oriented. Minimal APIs are functional.
If your domain model is object-oriented, then controllers are easier to integrate with them. If your domain models are functional, then integrating them into controllers is nothing but a royal pain.
Minimal API always seem like a way to get a proof of concept out the door quickly, nothing that I would ever put in production.
@@DevMeloy No, no. Minimal API is a serious tool when designing Web APIs. Once you get them right, you never look back at controllers again.
@@zoran-horvat Maybe I'm too averse to change but seem to gravitate towards a thin controller/service/repo architecture. Next time I have a green field project I will look into M-API again to see if the benefits outweigh the learning curve. Thank you for another amazing video :)
I don't use them even for this purpose (prototyping). The normal (also called traditional for some reason) APIs are just fine and so easy.
@lolyasuo1235 global usings and removing brackets on namespaces are a welcome addition, but sometimes it feels like the .NET team is making changes for the sake of change.
@@lolyasuo1235it would be cool to see a nice obvious example where Minimal APIs handily outperform their standard controller equivalents. I'm still so early on my learning journey.
Ah, nice to know I was doing it more or less right.
Really interesting...
I moved all my endpoints to static classes of logically grouped endpoints (don't call them controllers 😉) with the the MapGroup at the top of each. These static classes called UseAuthorEndpoint, UseBookEndpoint etc. each return the WebApplication for chaining.
I've left the logic for each endpoint in the endpoint lambda, which leads to my question. Is there any benefit to separating out the logic into static methods once everything has been tidied into these separate files?
Really love your work, My work day always starts with a calendar entry for revision that is usually one of your videos...
The hidden part of minimal APIs, which many programmers don't see, is that they are implemented as a functional library. With explicit static methods rather than lambdas, you retain all the functional tools that exist, primarily partial function application and monadic composition.
Not bad, but still not sufficient for me. I would use REPR pattern with minimal api endpoints with scanning (including groups/base groups etc.), so one endpoint per file - that contains all details about endpoint registration and endpoint executive.
My first thought at the beginning was that it would be a MediatR implementation, and this would be my approach if I would see such code. I'm glad that you proved me wrong - your way is much nicer. MediaR is ok and could do the job, but it will be too obvious and too mainstream compared to the level of quality of your channel. Thanks for the tip!
Now, to the refactoring-mobile 😂
@@serviceengine I don't like adding more libraries when vanilla code gets me to what I wanted to accomplish. That says nothing bad about the MediatR, which I think is good.
Thank you! I guess there's no way to avoid duplicating the common dependencies of the methods inside the static handlers classes?
@@johnnyutah23 I don't think that should be your goal in the first place.
@@zoran-horvat Probably not... in the past I've organized a minimal API project like you've shown but there were a bunch of methods that took many of the same dependencies, I was wondering if there was a better way
@@johnnyutah23 I say that because there is no duplication just because two methods accept the same dependency. The duplication might occur if they do the same thing, but the dependencies alone are not indicative of that.
What advantage controllers give you over minimal api?
Primarily the structure of a traditional OOP project. If you are used to object-oriented programming, then controllers are a natural choice, as everything in them is OO: from model binding, model validation, over actions, persistence, all the way to testing.
If, however, your code structure is more functional, based on static functions and separation of data from behavior, then minimal APIs seem like a modern, fast, and composable solution for future projects.
I'm just here to see how people manage to mess up minimal APIs
I'm still not convinced this is much better than using Controllers once your application grows to a non-trivial size
@@shadowsir That's what I said in the video - if the model is large, minimal API is probably not the right tool for it. And vice versa. A limited, focused model, which only manages one domain concept, likely doesn't warrant the added complexity and weight of controllers.
To be frank, this seems to me you just implemented a worse version of controllers.
If you start from the differences between minimal API and controllers, then you will quickly realize that it is not.
Could it just be that you have developed a habit of writing controllers and now you cannot look away from them?
@@zoran-horvat I know there are differences between the two approaches and both have their place. But what exactly did you gain by doing this refactoring exercise? Correct me if I'm wrong, but if you redo this with controllers you'll end up with the same number of classes, less code in both the controllers and Program.cs, and arguably an architecture that's more predictable/standard.
You keep looking at the wrong spot, and then you see me create classes. But you saw it wrong. I created no classes in the demo. Check it out.
Nice video Zoran, although this is more a presentation on the Single Responsibility Principal and how to refactor code to achieve this. I would go even further and separate out the service configuration and endpoint configuration into separate methods/classes.
Minimal API has been used as an excuse by lazy engineers to not implement SRP. And if anyone were to present the initial code to me for review in a PR, that PR would be very quickly refused.
@@John.Oliver That is correct about code review. The initial code, which I have seen quite a few times, is indicative of an irrational belief that minimal API is so small it doesn't require common programming.
@@zoran-horvat I've seen that too. Thanks mate. Great video.
can share the source code?
why not fastendpoints? also thanks for the video, beatiful refactoring
That could be one of the next videos, depending on interest. I always do the vanilla approach first, because that is what the framework and the language offer.
My eyes opened the moment I applied the REPR and CQRS patterns to route-grouped Minimal APIs.
Yes, this example will evolve into that direction, hopefully in the next video.
Give me one valid point to use fancy things there out instead of traditional APIs which is the best way to go. They are so simple so there is no excuse. Why not to go? they are "fat"? I am going to get 29.9k RPS instead of 30.5k RPS (minimal APIs)? So What. And the minimal APIs are reinventing the traditional APIs so its waste of time.
@@lolyasuo1235 What is traditional API and how is it not fancy?
Don't confuse my brain, a free crash course from you at least will help😊.
Don't forget no single crash course in your channel.
I plan one soon, but that takes a completed mini-series first, which takes a few months in its own right.
@zoran-horvat ❤❤❤❤❤❤ trillions love from Nigeria 🇳🇬
The more I see these workarounds and tips surrounding minimal APIs the more I like the out-of-the-box simplicity and intuitiveness of good ol' controller classes. All this work and we end up with basically the same thing as there, except more obfuscated and bloated with mapping code and methods that used to be just [Route("foo")]
@@kaldo2113 What controllers are in OOP, minimal APIs are in FP. How would you design a functional controller?
@@zoran-horvat I'm not sure what a functional controller would even be, but as far as I can tell all the routes in the video could be easily rewritten with the old controller approach? The whole set of handler classes with static methods and the required registrations in program.cs just seem like unnecessary code compared to having them intuitively separated by controller classes and having mappings defined right next to the controller method (and the code using them).
I kinda disagrez about "Minimal API m" being used for "smaller projects"
A well structured minimal api project is faster and also is more explicit.
Even microsoft themselves only show it in one file on the doc just for convenience, that's not really how a bigger project would do it. And i bet bigger projects could still use Minimal api, or maybe FastEndpoint.
I wouldn't go back to controllers personally.
@@WDGKuurama There is one hidden gem in them, which many people never saw. Unlike controllers, which are object-oriented, minimal APIs are functional. If you can organize your project the way functional projects are organized, then minimal API will be the more convenient form for the Web layer. I plan a video about that in the near future.
@zoran-horvat Yoo neat
A file isn't limited to a single class (or even namespace), if they want to shove everything together for "convenience".
First!
We're going further, extracting each handler into the own static class - file per handler.
Second!
makes messy code, tells us code is messy
@@notoriouslycuriouswombat Can you identify what is messy, precisely? I didn't change a single line of code during the refactoring, and yet, the final implementation I wouldn't call messy.
I feel like you had fun making that program.cs as horrible as you could
@@Robert-yw5ms Well, no. That is a complete implementation of just a few endpoints with nothing missing - especially validation and the proper construction of error responses. There is nothing specifically wrong there.