C# Minimal APIs Quickly Get Messy - Clean Them Up!

Поділитися
Вставка
  • Опубліковано 9 січ 2025

КОМЕНТАРІ • 102

  • @Krapvag
    @Krapvag Місяць тому +22

    strangely satisfying when you watch a video and go "oh I already do this! cool!"

    • @zoran-horvat
      @zoran-horvat  Місяць тому +3

      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.

  • @MahmoudSaed98
    @MahmoudSaed98 Місяць тому +8

    Your way of explaining is very wonderful and so is your way of speaking. You are literally the godfather of programming.

  • @Ovsr-x1w
    @Ovsr-x1w Місяць тому +4

    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

  • @GigAHerZ64
    @GigAHerZ64 Місяць тому +7

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +2

      @@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.

    • @JanVerny
      @JanVerny Місяць тому

      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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      @@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.

    • @jordanfarr3157
      @jordanfarr3157 Місяць тому +3

      ​@zoran-horvat do I hear a new video title???

    • @BramtenBrinke
      @BramtenBrinke Місяць тому

      @@zoran-horvat Id be very much interested in that as well

  • @harunaabaldeh2006
    @harunaabaldeh2006 Місяць тому +5

    The way you talks keeps me watching until the end! Education + Entertainment = Happy Coding

  • @Tesfamichael.G
    @Tesfamichael.G Місяць тому +3

    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!

  • @gpltaylor
    @gpltaylor 19 днів тому +1

    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?

  • @DynamicalisBlue
    @DynamicalisBlue 9 днів тому +1

    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.

  • @michapolaszek7049
    @michapolaszek7049 Місяць тому +1

    Great movie! In 9:50 you could have pressed Ctrl + R, Ctrl + G to remove unneeded using-s.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +2

      I always do, but here I wanted to make it last longer, for the feeling of deleting it with my bare hands :)

    • @michapolaszek7049
      @michapolaszek7049 Місяць тому

      @@zoran-horvat :)

  • @WarpingWombat
    @WarpingWombat Місяць тому +1

    Great Video! Always satisfying to clean something up. I would prefer a vertical structure along the usw cases though

  • @peterhamilton1970
    @peterhamilton1970 Місяць тому +1

    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

  • @DullingWine
    @DullingWine Місяць тому +1

    Excellent tutorial Zoran!

  • @sotsch9280
    @sotsch9280 Місяць тому +1

    Another piece of gold from you!

  • @JakobStrasser
    @JakobStrasser Місяць тому +1

    Wow, that's the cleanest program.cs I've ever seen!

  • @warrantor
    @warrantor Місяць тому +1

    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!! 😉

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      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.

  • @GeromeGuillemin
    @GeromeGuillemin Місяць тому +1

    Extra nice work!

  • @TheKoneko1312
    @TheKoneko1312 Місяць тому +1

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      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.

  • @billy65bob
    @billy65bob Місяць тому +1

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      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.

    • @John.Oliver
      @John.Oliver Місяць тому

      @@zoran-horvat Correct, although it should not by used as an excuse for not implementing out SRP.

  • @dabest9843
    @dabest9843 Місяць тому +2

    Science that is advanced enough will be mistaken to be magic. This is magic without a doubt. The magic of abstraction.

  • @7th_CAV_Trooper
    @7th_CAV_Trooper 23 дні тому

    I think of minimal API as a routing/mapping mechanism. Every method is only one line to call a method on a domain service.

  • @desertfish74
    @desertfish74 Місяць тому +1

    Excellent video. Thanks

  • @luc9volts
    @luc9volts Місяць тому +1

    Very good solution

  • @petervo224
    @petervo224 Місяць тому +3

    0:34 I thought I would hear "One File to rule them all" lol

  • @unexpectedkAs
    @unexpectedkAs Місяць тому

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      @@unexpectedkAs That shows how closely related all those ideas are.

  • @vitahvitah5823
    @vitahvitah5823 Місяць тому +1

    Very nice topic. Thanks

  • @prec6383
    @prec6383 Місяць тому +2

    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?'

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      @@prec6383 I had that moment once, too.

  • @Muhammadsaleh77
    @Muhammadsaleh77 Місяць тому +1

    Dear Mr. Zoran,
    I hope my comment finds you well.
    Please keep going with such great videos.
    Yours 🎉

  • @marcobaccaro
    @marcobaccaro 28 днів тому

    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.

    • @zoran-horvat
      @zoran-horvat  28 днів тому

      @@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.

  • @DevMeloy
    @DevMeloy Місяць тому +1

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +5

      @@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.

    • @DevMeloy
      @DevMeloy Місяць тому +1

      @@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
      @lolyasuo1235 Місяць тому

      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.

    • @DevMeloy
      @DevMeloy Місяць тому +1

      @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.

    • @jordanfarr3157
      @jordanfarr3157 Місяць тому

      ​@@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.

  • @Mortizul
    @Mortizul Місяць тому +1

    Ah, nice to know I was doing it more or less right.

  • @ScottBarnesBass
    @ScottBarnesBass Місяць тому

    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...

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      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.

  • @Eltin123456
    @Eltin123456 Місяць тому +1

    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.

  • @serviceengine
    @serviceengine Місяць тому +1

    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 😂

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      @@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.

  • @johnnyutah23
    @johnnyutah23 Місяць тому

    Thank you! I guess there's no way to avoid duplicating the common dependencies of the methods inside the static handlers classes?

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      @@johnnyutah23 I don't think that should be your goal in the first place.

    • @johnnyutah23
      @johnnyutah23 Місяць тому

      @@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

    • @zoran-horvat
      @zoran-horvat  Місяць тому +2

      @@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.

  • @emanuelrodriguez3155
    @emanuelrodriguez3155 Місяць тому

    What advantage controllers give you over minimal api?

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      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.

  • @tuyvuvan9307
    @tuyvuvan9307 Місяць тому

    I'm just here to see how people manage to mess up minimal APIs

  • @shadowsir
    @shadowsir Місяць тому

    I'm still not convinced this is much better than using Controllers once your application grows to a non-trivial size

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      @@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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      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.

  • @John.Oliver
    @John.Oliver Місяць тому

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +2

      @@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.

    • @John.Oliver
      @John.Oliver Місяць тому +1

      @@zoran-horvat I've seen that too. Thanks mate. Great video.

  • @rahiyansafin449
    @rahiyansafin449 Місяць тому

    can share the source code?

  • @деменция-н4п
    @деменция-н4п Місяць тому

    why not fastendpoints? also thanks for the video, beatiful refactoring

    • @zoran-horvat
      @zoran-horvat  Місяць тому +2

      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.

  • @hanufeenstra2061
    @hanufeenstra2061 Місяць тому +1

    My eyes opened the moment I applied the REPR and CQRS patterns to route-grouped Minimal APIs.

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      Yes, this example will evolve into that direction, hopefully in the next video.

    • @lolyasuo1235
      @lolyasuo1235 Місяць тому

      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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      @@lolyasuo1235 What is traditional API and how is it not fancy?

  • @generalchannel8833
    @generalchannel8833 Місяць тому

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +1

      I plan one soon, but that takes a completed mini-series first, which takes a few months in its own right.

    • @generalchannel8833
      @generalchannel8833 Місяць тому +1

      @zoran-horvat ❤❤❤❤❤❤ trillions love from Nigeria 🇳🇬

  • @kaldo2113
    @kaldo2113 Місяць тому +1

    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
      @zoran-horvat  Місяць тому +1

      @@kaldo2113 What controllers are in OOP, minimal APIs are in FP. How would you design a functional controller?

    • @kaldo2113
      @kaldo2113 Місяць тому +3

      @@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).

  • @WDGKuurama
    @WDGKuurama Місяць тому +1

    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.

    • @zoran-horvat
      @zoran-horvat  Місяць тому +3

      @@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.

    • @WDGKuurama
      @WDGKuurama Місяць тому +1

      @zoran-horvat Yoo neat

    • @billy65bob
      @billy65bob Місяць тому

      A file isn't limited to a single class (or even namespace), if they want to shove everything together for "convenience".

  • @weluvmusicz
    @weluvmusicz Місяць тому +1

    First!

  • @ml_serenity
    @ml_serenity Місяць тому

    We're going further, extracting each handler into the own static class - file per handler.

  • @phreakadelle
    @phreakadelle Місяць тому

    Second!

  • @notoriouslycuriouswombat
    @notoriouslycuriouswombat Місяць тому

    makes messy code, tells us code is messy

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      @@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
    @Robert-yw5ms Місяць тому

    I feel like you had fun making that program.cs as horrible as you could

    • @zoran-horvat
      @zoran-horvat  Місяць тому

      @@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.