Thank you Nick, I like it :) The only thing I would change in example - services registration - do it once in one place, otherwise we will have multiple Add(Scoped/Transient/Single) of the same interface+implementation. And I thing old functional services can be useful here - you don't need extra delegate, just use service that does all work related to Customers (for ex.) - validation/logic security check/business logic/work with repo. And this service can be tested easily.
It seems in a "more practical" use case, the code ends up looking similar to the "old way". That being said, the fact that registration is done via method call and the performance gain makes this a huge step up from the prior way of doing things. People can more easily write generic generators for API handlers which could drastically reduce code for certain use cases and still gain a performance boost. I'm very excited about this feature!
Great job! Actually I was a bit skeptical of the minimal API as well, but you highlighted a great way of real world setup. It is almost better readable compared to controller-style. Just one point was missing for: how to do API versioning now or method annotation (e.g. Consumes/Produces attribute)?
Hi Nick!! You're a .Net Jedi ;) I really appreciate you made this continuation video on the Minimal Apis. I was researching on how to refactor all from your 1st video and a week later discovered you already explained in a far bettter way than my reasearch. Thanks also for the additional NBoomer tip that I also did not knew about it. Super cool!!
I like the mapping of one endpoint to one file, and then wrap them up in the end. But this is a cool approach, I am still learning C#. C# is more powerful than it appears on the surface. It's like the best of both world, as if C++ and Java had a baby! Its great. Great video! Learning tons.
Great video!! 👍 Thank you so much!! I will looking for more videos from you about build Minimal API and best practices with them! Please, keep your good work!
@@OOpSjm because "Enterprise" has been synonymous with bloated, poorly performing, unmaintainable programs. Typically this was the case ever since Java when simple coding methods were thrown out in favour of every "cool new way" that appeared so often. Too bad C# looks to be exactly the same!
Oh got to the 4:30 mark and that endpointdefiniton method is something I was looking for. Was going through this with a dev yesterday and I hated the ugliness of the program.cs so ended up doiing something very similar to you but ended up using DI in the program.cs to get transient instances of my endpoint services and loop through them to set up the endpoints. The way you show is more elligant and I may log on to my work laptop later to make the changes.
As I was watching the video, I was thinking, "Why would I divide the endpoints like that into separate definition classes? It makes the minimal API look almost like the old controller-based approach." Then I looked at the performance benefit and realized the reason. I remembered that Daniel Roth had said that minimal APIs would perform much better than controller-based APIs. Nevertheless, I would have liked to see a comparison of performance between the controller-based API, the original minimal API with the "bloated" Program.cs, and this new minimal API with the reflection-based lookup. Furthermore, I think that moving the endpoint-handler methods from the old "bloated" Program.cs into a separate class would be enough to make it scalable enough. Great video, btw, as always 👍🏽
The performance is exactly the same. The reflection used for endpoint registration has 0 effect on the API's performance because it only happens once at startup and builds on existing methods.
This video is amazing and a fantastic explanation. It really helped me. I guess the point of transforming the functional API into an OOP one is to appeal to people from an OOP background? Presumably you wouldn’t want to do that in reality?
Looks great! I believe it will look even cleaner when IMediator is injected in the endpoint definitions instead of the ICustomerRepository. NBomber looks like a great library btw! Do you use that library a lot for load testing?
I originally planned to show this with Mediator but I think it would complicate it a bit with all those files so I kept the simple verison, buy you are totally right. Mediator will play really nicely with this.
This was really awesome video. Lots of cool stuff and real world examples. Thanks!
3 роки тому+1
I have a issue, I have a projects in clean arch, Domains, application, Ioc (dependencys), mvc, infra.data, all clean and separed classes, so, I create a new project workerservice (for create a windows service) but is impossible add referencies all project (services, repositories and context class) in a workersercices becose workersercice is a SingleTom. the same issue is happaning if I create a api project becouse its projetc is a singleton too. I cannot reuse my codes (services, viewmodels, and repositories) Are you have a ideia for I implement this solution? inject a complex dependencys in a singleton project?
I am checking your video after a long time and thanks for this lesson. I have seen your NDC conference and came here to check what you have for us. With regarding to coding style , If we have to refactor it by creating endpoint classes implementing Iendpoint interface and registering only the required services for the endpoint to maintain SINGLE RESPONSIBILITY Then can we not also follow the same without using the minimal api way, using controllers? Like only using the controller for specific endpoint? Its there readymade, so why we need to take such approach and use minimal api ?
I think the real sauce for minimal APIs will be using them for service to service communication. I'd prolly just use a minimal api leveraging grpc comm between multiple services.
Some people don't seem to realize that the singe file approach is just a marketing tool. The ASP.NET team doesn't expect you to write your whole api in a single file...
Can I request you reduce font by 1pt? I understand large text is useful for video, but if we can't see the all of the text, it's hard to understand. Witness 10:59, top of screen.
Trouble I've found is that returning Task doesn't return TypedResults.... in Swagger for example you won't see the media type as "application/json" or the schema under Description.
Liked. While i disagree with the overabstraction as it is against the point of minimal apis, the performance you gain is something you can't ignore. Ofc i would like to see the "real" performance gain in production with lot of APIs/data. PS: @all is unit testing important for minimal apis? do we really need it? if the project is that complex then maby we should use the classic way? idk...
This is faster because you are bypassing the ASP.NET MVC framework which is pretty bloated and comes with a perf cost. I like the minimal APIs, it's very similar to Giraffe/Suave in F#. It's a perfectly good way to compose a large application together.
Bloated... compared to what? As a corporate developer/architect that's implemented every .NET web version since 1.0, I can tell you the benefits of a framework like MVC far outweighs any performance detriment, especially for junior devs. The only time I would consider using this approach is for extremely light-weight POCs. But this will not scale when you teams of devs running sprints, and you need common framework components like audit, logging, authentication, authorisation, etc. If you started at the mimimal point and added all the middleware stuff to get it all running .... you've just implemented MVC. When you implemented authorisation policies, cross check bearer/auth tokens ( you are authN/authZ your API calls... yes? ), write to audit services, call DBs and other external service endpoints... any "bloat" from the MVC/Route pipelines will disappear. This is been my experience with development large scale web applications ( '000s of concurrent users ) on .NET technology stacks over the past 20+ years.
@@robslaney3729 Not all web apis need all features. Even some "big" apis just need some authentication and go live. Also not all companies follow strict processes. Even the companies who follow some "Scrum" guide have projects that need just to get shiped fast. My point is: minimal apis still viable solution. Howver, i like your answer. People already started "how do i X, how do i Y with minimal apis...". I wish people don't end up "implementing MVC" as you said. For more complex apis or if your team is not happy with maintaining minimal apis, the just go classic apis.
@@shakeuk It was like 5k/30k performance gain. So a 20% performance gain WHICH IS AMAZING. However we must wait the final release of NET6 to see how classic apis will perform. Also there are so many things to consider here: - he is benchmarking on top AMD CPU with 12/24 ct(?)... when you propable don't even get the half of this power in cloud, and you scale via adding instances. - what about some real world operations? efcore/databases/IO/authorization...
@@robslaney3729 Well it's bloated compared to ASP.NET. That's not to say if you need to leverage what the MVC framework has to offer and it makes your life easier, by all means, that's a judgement call you make. I obviously do not recommend re-inventing your own framework on top of Minimal APIs. As a developer/architect myself, we have a lot of backend APIs that really are just LOTS of CRUD operations, or store and forward, or an entry point etc. There really is no need to over-engineer these kinds of APIs. The simplicity of Giraffe has been well suited to this and Minimal APIs I think are great fit here as well. Juniors tend to copy what already exists in your codebase. If they see a structured example or are adding to a structured codebase, that is the pattern they will follow. In many ways Minimal APIs can lower the barrier to entry for juniors extending your APIs.
This seems like a really nice approach. Would you recommend this for someone building a new application over the standard HostBuilder approach? When would you *not* recommend this approach? I've been rebuilding my website with a Blazor WASM frontend and was looking to add an API to it, and was thinking about how I could make better use of generics and minimize boilerplate.
@@nickchapsas But it will be possible to use attributes with final C# 10. app.MapGet("/api/todos", [Authorize](TodoDbContext db) => (db.todos.ToListAsync());
Maybe you could do a minimal Api version with EF Core? -im thinking about the stuff to do in the repositories and if you would do data validation and send back if properties are not valid or does not meet requirements. EF Core has the methods to create, post and delete objects so im not sure if i can skip the Repository part where you have GetById, Delete and Update because they already exist in EF Core
so if i want to inject my database and im using EF Core in my Rest Api Server, i would just have to replace your CustomerRepository in the DefineServices with ApplicationDbContext where i have all my DbSet methods?
Great video Nick - I've just started using minimal APIs but find the unit testing is sub-optimal. I'm using XUnit+Moq, but IResult is returning classes that are marked as internal (Results.Ok, Results.NoContent etc) making it much more tedious to test. Do you have a good solution for this without going via serialise / de-serialise cycle with mock classes?
This is just my opinion. I feel like minimal APIs are good for some cases like fast Prototyping, Mocking Services and of course real Microservices. Imaging having an Azure Function, AWS Lambda or even a simple Container. This can lead not only a performance boost on your application but your entire development life cycle. Microservices in a single or minimum files means self-contain apps with minimum size, so you can build, test, release and deploy in less time. Once in production, that same small app can scale faster and I assuming that even have a better response after a cold start. Minimal APIs are not just good or bad. All depends on the context of what you have, and what you need. We need to constantly change our point of view on how things are done. A well designed microservice architecture will be benefit of this approach. Can you imagine having a single file for each microservice like Customers, Sales, Providers, etc? This enables having even less effort for developers to understand, create, maintain services. Sure, this creates complexity outside the app itself. As monolith architecture may not benefit in the same way as you expect to have everything in one entire solution. Find the best that fits for your requirements and remember, sometimes the client or the business has the last word :P
Am wondering how you apply special attributes to those delegates like you would in a controller? Things like auth or swagger attributes etc Ive been meaning to use this sort of stuff not for minimalism but for modularity/split between the module that has logic and any special hosting logic. Also if you didn’t know if you brig up riders context action menu there is an extract interface button so you dont have to copy by hand :)
You can apply attributes to delegates now but you can also use the Fluent API approach and chain those methods, for example ".Produces(typeof(Customer))"
This is very interesting, I like the cleaner style. But, what about attributes for services like auth, or return response type info for swagger or such? Seems like that will make the app routing awkward. It'll look something like app.MapGet("blabblah", [Authorize("Policy=Readonly")], [ProducesResponseType(500)] UpdateCustomer); Not sure how that could be cleaned up. Multiple response types could add to the clutter. Not that it's any more code than the "old" way, but I like the minimal api direction/style, and hate it see if become less attractive due to attributes.
2:10 You shouldn't have continued with the refactoring in a red state of error as you could be adding bugs to the code. This could have been a good way to demonstrate how to refactor a legacy application (aka, an application without unit tests) into a modern, maintainable application.
I’ve already done that in my 2 part refactoring exercise. This video isn’t refactoring but re-organisation but I called it refactoring because it’s easier to understand me click
Well... That's better. What about multiple attributes (ex: Authorize, ApiVersion... etc)? Can we place their right into Map methods? Dunno.. This is a really good solution for PoC, I agree. What happens when we add all the necessary attributes and others elements just like in the big serious enterprise project? Yes.. this will be controller! %)
i thik this kind of solutions work very well with microservices, and a good api manager so you can leave authorization tasks and versioning to the api manager and focus only the task that needs to be done
@@nickchapsas well, I mean more complex projects rather than simple ones. If we are going to have a lot of endpoints with the different models,then thing will be getting complicated I guess. But with old-style approach everything stays fine.
@@hasan_shans I don't work with such projects so I can't give you the best advice there but the controller based approach would probably be better there. I only work on high scale/performance/throughput microservices, which Minimal APIs are a perfect fit for
How will you resolve Constructor based Dependency Injection in Minimal API. For eg. in your code ICustomerRepository has to be passed as a parameter in every method of the class, unlike Controller based approach where we would add Dependency at Constructor level. If we have multiple commonly used Dependenices e.g. MediateR, AutoMapper, ApDbContext then all of this needs to be passed in each method. Then how will you handle this?
You don't do constructure based DI in minimal APIs. You do Action based injection. If you want constructor based injection with minimal api tech then use FastEndpoints
Please do a video about designing a proper WebAPI project using modern C#. Edit: My mistake, I just need to search back several years. For other readers, Nick has an entire course here: ua-cam.com/play/PLUOequmGnXxOgmSDWU7Tl6iQTsOtyjtwU.html It covers only up to .NET 5, but I suspect changes are minimal as WebAPI is fairly mature.
It looks very interesting, but also just like reinventing a bit faster controller with extra steps. GetAllCustomers/UpdateCustomer/DeleteCustomer - all in all we have the same methods defined both in EndpointDefinition and Controller. EndpointDefinition just has to implement an extra step to map internal methods to routes (which is done in controllers automatically or with route attributes) and injecting services (which anyway has to be done in both approaches, but there "controller" has to know about the implementation). As a result we have 13% higher performance (and maybe even higher as you said, but maybe lower if endpoint has comlicated logic) with extra infrastructure and a bit boilerplate code in "better controller". If application really needs this performance boost then yeah it makes sense, but in other cases it smells like overengineering.
I find controllers for APIs an anti pattern. The only reason they exist are because they just happened to be there when MVC came along and Microsoft rebranded them as WebAPI because they didn’t want to build a cleaner more focused version. The fact that a controller has N amount of method for actions that only loosely belong together is such a bit single responsibility violation
@@nickchapsas you call it antipattern, but still use it just in differently named class with extra methods from interface. What problem is to store unrelated methods in different controller? You can still define full route with attribute as you do it in Minimal API. The only advantage of your approach is a higher performance (which could become a deciding factor though). Maybe the problem around controllers as WebApi is not in technology but in a long period of using them improperly which became a bad practice. In my opinion they are flexible enough to use them in correct way.
@@oleksandrnikonov8383 This video is largely outdated, and the update is the FastEndpoints video. Having a single class per endpoint structured in a vertical slice is a far better approach. I forgot I had the all the minimal api endpoints in a single class in this video.
4:40 Using an arbitrary type here on Program.cs line 5 seems fishy. The code looks like it is specifically doing something to the Customer class, but it could very well be doing those things for the entire assembly? If I'm tasked with adding a new model class to this application, it'd be quite confusing that I don't also need a line for whatever class I'm adding. I feel like it would be clearer if it was more explicit about taking an assembly by name rather than a class in that assembly.
Assembly scanning isn't a new concept. MediatR, Automapper, FluentAssertions and basically every other library does the same thing. It's up to the user to read the doc. A most common practice is to use what is called an "Assembly Marker" which is usually just an empty interface, but I didn't wanna dive into that in this video.
@Nick Chapsas Consider if the line was this instead: builder.Services.AddEndpointDefinitionsFromAssembly(Assembly.GetAssembly(typeof(Customer))); There would be no need to read the doc. It's slightly longer, but saves the tech debt.
@@KelvinNishikawa Naming is completely up to you. You can even go with services.AddEndpointDefinitionsFromAssemblyContaining(). Like I mention in the video, you should not treat whatever you see in this or any video as the de facto solution. Change things up to your own taste.
What about the other things we might take for granted like model validation? And the decorator 'apicontroller' which auto checks modelstate and returns a bad request etc. You didn't have that on your simple API, if it doesn't have that in or enabled, maybe that's why it's more performant, I could be wrong because I haven't checked the docs for all the features of the minimal API. Additionally swashbuckle has additional decorators for enrich the openapi output, how would one use those with this approach without digging into the swashbuckle filters or writing custom secret sauce code to do that... Hopefully some new nuget packages will come out, but by the time u have done all that ... Won't you just have controllers again?
You can do all that in minimal api. Model parsing still happens in both of them since they parse the route parameter. Validation doesn't happen in any of them. For Swashbuckle you can simply use the fluent ".Produces()" methods. There are multiple blogs that showcase how to handle valiation in Minimal APIs. I don't think I've ever seen an app that actually goes to prod with the built in MVC model validation. Everyone replaces it for FluentValidation either with a Mediator pre processor or a middleware, which is possible in Minimal APIs too.
@@nickchapsas yes we use fluentvalidation as well since we don't like coupling validation to the models also fluentvalidation makes it really easy to write custom validation rules and unit test your model validation.
@@nickchapsas yes you may not have any validation in your sample projects but because you are using the typical middleware (including the apicontroller decorator) the aspnet core framework will still go through its pipeline which will include the modelstate check for every request. Your minimal API might not do in your example which could explain some of the performance gains... Again I could be wrong since I have not used the minimal API it dug into its features and or configurations.
Hey Nick, thanks for great content! One question...Is it possible to combine classic controllers and minimal api and if so: do we get the same performance benefit when we hit endpoints implemented using minimal api within such combined solution?
@@nickchapsas actually i am more interested in the opposite case: do minimal api endpoints still gain performance benefits even when they are within the solution where classic controllers are used as well?
@@nickchapsas just a bit of a background... i have a project in which i have dozen of controllers which are not performance critical and for which i definitely have benefits of their well established infrastructure/ceremony. at the same time, i have 2 particular endpoints which get unsymmetrically more load. so, if i could get benefit in implementing just those 2 endpoints using minimal api, that would actually be 15% for free which would be awesome.
@@donnyroufs551 you can have two repositories, that implement the same interface, but one is reading dats from real db and the second you write for specifically return test data. Than you can create instance of your service, but provide test repository for it, so you can test your service without any interaction with DB. You can't do these things in another way without duplicating business logic. You can write the same business class with the same logic, of course, but than you must always bring the changes from your real class to test class. This would be a mess.
@@donnyroufs551 short answer you can't. It is a big theme: unit testing. I recommend watching videos about it and/or read books about it. Unit testing is chained with dependency injection, so search for this term too. And just try it yourself, practicing and mistakes are the best teachers.
I have subscribed to your channel for about 2 months, but I still don't have a roadmap to get started on how to learn C# .Net, can you guide me a bit. Thank you very much. P/s: sorry I used gg to translate
In reviewing this I do see that Nick has shown an alternate method of defining API's, but is not clear what the advantage to this is. There is still quite a bit of secret sauce being implemented all of which hides this and that....but overall not clear what is the actual purpose/advantage of this over just doing the standard method? "Simpler" seems like a misnomer as is hides much of the mechanics and that is not actually simpler. Please Nick do not take this as a criticism of your video, your thoughts are always appreciated. Just my thinking as developers change in and out of our teams, seems like simpler remains the most obvious way.
It feels like you invented controllers again to handle the issues that were broached. To avoid the bloating issue, use endpoint definitions (controllers), to make it more testable you created methods for the delegates. There are issues with this home grown approach though, how do we avoid registering the same service multiple times if you have different endpoints in different files requiring the same object (e.g. customer repo). I believe minimal apis are not a drop in replacement for controllers but more for prototyping, simple use cases. I'm not impressed with the load testing performed, I assume there would be some gains with minimal api because controllers are scoped per request (meaning they get created and GCed), while minimal api delegates are essentially singletons. Would need a more complex example like doing some IO and not completely in memory to measure the realistic gains. I do enjoy the ability to use minimal apis and the flex .net 6/c# gives me between prototyping and full fledge development. Just my two cents.
Many false things in this comment so let’s clear some things up. First, no I didn’t reinvent controllers. This is the REPL pattern implementation, completely different from MVC, which is where controllers come from. The key here being that one handlers belongs to one request and has one specific response. Yes this is different, also no, you don’t have to worry about the same service twice because you should be using the TryAdd alternatives to DI, not the Add ones. When you are adding any package you don’t know what they are registering internally and if you don’t use TryAdd you end up with the same issue. Minimal APIs shine both in simpleuscases and also micro services due to the simplicity of microservices by nature. Also no they are not faster because they are singletons. In fact, they are scoped exactly as the controller ones. They are faster because they don’t use a lot of filters and middleware the controllers automatically use but you don’t need. It’s a remnant of the MVC world which was repurposed mostly. Memory is less and method jumps are less so they end up faster.
Why is this limited to APIs? Why couldn't you build an entire website like this: app.Map("/", async (context) => {await context.Response.WriteAsync("...Example Page Output");});
Well - I'm not a big fan of this minimal apis, but: If we combine it with CQRS, it could be a really nice option. With nice extension methods (like "MapQuery" or "MapCommand"), that just use the minimal api methods, we can have all endpoinds in one single and easy to understand file. And then we have the advantage of minimal APIs and no additional overhead in a controller that only calls the mediator. This could be a realy nice way to create web apis with CQRS.
Thank you Nick, I like it :) The only thing I would change in example - services registration - do it once in one place, otherwise we will have multiple Add(Scoped/Transient/Single) of the same interface+implementation. And I thing old functional services can be useful here - you don't need extra delegate, just use service that does all work related to Customers (for ex.) - validation/logic security check/business logic/work with repo. And this service can be tested easily.
It seems in a "more practical" use case, the code ends up looking similar to the "old way". That being said, the fact that registration is done via method call and the performance gain makes this a huge step up from the prior way of doing things. People can more easily write generic generators for API handlers which could drastically reduce code for certain use cases and still gain a performance boost. I'm very excited about this feature!
can you please explain security things in minimal Apis that supported by controllers with attributes/action filter?
Great job! Actually I was a bit skeptical of the minimal API as well, but you highlighted a great way of real world setup. It is almost better readable compared to controller-style. Just one point was missing for: how to do API versioning now or method annotation (e.g. Consumes/Produces attribute)?
This video was really needed, minimal API is so awesome. Thanks
Hi Nick!! You're a .Net Jedi ;)
I really appreciate you made this continuation video on the Minimal Apis. I was researching on how to refactor all from your 1st video and a week later discovered you already explained in a far bettter way than my reasearch. Thanks also for the additional NBoomer tip that I also did not knew about it. Super cool!!
I like the mapping of one endpoint to one file, and then wrap them up in the end. But this is a cool approach, I am still learning C#. C# is more powerful than it appears on the surface. It's like the best of both world, as if C++ and Java had a baby! Its great. Great video! Learning tons.
I hope your learning of C# goes well
Fantastic video look forward to showing my Dev team a potential rewrite of our APIs
They are almost there. This isn't yet as practical as the MVC setup. This is getting a lot closer to NodeJS w/ Express, which I find to be quite good.
Looks like, in the end, you've created a proto-controller
Great video, thanks! could you plz add more features like authentication and authorization to it.
Great video!! 👍 Thank you so much!! I will looking for more videos from you about build Minimal API and best practices with them! Please, keep your good work!
This is so much cleaner in my opinion. Great job refactoring this! 👍🏻
Much needed video.
The air quotes and eye roll when you said "enterprise". 🤣
at 0:30 in case you're reading comments after watching the whole thing
But, why?
@@OOpSjm because "Enterprise" has been synonymous with bloated, poorly performing, unmaintainable programs. Typically this was the case ever since Java when simple coding methods were thrown out in favour of every "cool new way" that appeared so often. Too bad C# looks to be exactly the same!
Minimal APIs reminds me of NancyFx. With that framework, endpoint definitions are added to a NancyModule to "group them".
Μπράβο Νίκο! Great vid as always. 👌🏼🙌🏼
Clear, elegant and beautiful, good job man as always.
Can you do a video of dynamically loading the types from assembly that you're doing in EndPointExtensions?
Oh got to the 4:30 mark and that endpointdefiniton method is something I was looking for. Was going through this with a dev yesterday and I hated the ugliness of the program.cs so ended up doiing something very similar to you but ended up using DI in the program.cs to get transient instances of my endpoint services and loop through them to set up the endpoints. The way you show is more elligant and I may log on to my work laptop later to make the changes.
Great Approach!!
Much better overview of the new stuff, but besides RPS stats can we you also add memory profiles? Probably utilize remote Instance.
Cool I didn't know about NBomber. I'd like to learn more about web api scalability. Left a like.
Thanks Nick. This is really awesome. Well descriptive and quite informative.
As I was watching the video, I was thinking, "Why would I divide the endpoints like that into separate definition classes? It makes the minimal API look almost like the old controller-based approach." Then I looked at the performance benefit and realized the reason. I remembered that Daniel Roth had said that minimal APIs would perform much better than controller-based APIs.
Nevertheless, I would have liked to see a comparison of performance between the controller-based API, the original minimal API with the "bloated" Program.cs, and this new minimal API with the reflection-based lookup.
Furthermore, I think that moving the endpoint-handler methods from the old "bloated" Program.cs into a separate class would be enough to make it scalable enough.
Great video, btw, as always 👍🏽
The performance is exactly the same. The reflection used for endpoint registration has 0 effect on the API's performance because it only happens once at startup and builds on existing methods.
This video is amazing and a fantastic explanation. It really helped me.
I guess the point of transforming the functional API into an OOP one is to appeal to people from an OOP background? Presumably you wouldn’t want to do that in reality?
Looks great! I believe it will look even cleaner when IMediator is injected in the endpoint definitions instead of the ICustomerRepository.
NBomber looks like a great library btw! Do you use that library a lot for load testing?
I originally planned to show this with Mediator but I think it would complicate it a bit with all those files so I kept the simple verison, buy you are totally right. Mediator will play really nicely with this.
@@nickchapsas Can you make a video about it?
@@weluvmusicz You can check out Nick's video on MediatR here :) ua-cam.com/video/YzOBrVlthMk/v-deo.html
@@weluvmusicz It will be showcased on Thursday's video and it might get a dedicated video too
@@nickchapsas Sounds fabulous!
Hi! Nick thank you very much for these wonderful tutorials.
could you put Minimal APIs series together in playlist thanks again.
Great explanation, thank you!
Great video. Thanks Nick!
thank you so much for the demo, it's a big help for me :)
This was really awesome video. Lots of cool stuff and real world examples. Thanks!
I have a issue, I have a projects in clean arch, Domains, application, Ioc (dependencys), mvc, infra.data, all clean and separed classes, so, I create a new project workerservice (for create a windows service) but is impossible add referencies all project (services, repositories and context class) in a workersercices becose workersercice is a SingleTom. the same issue is happaning if I create a api project becouse its projetc is a singleton too.
I cannot reuse my codes (services, viewmodels, and repositories)
Are you have a ideia for I implement this solution? inject a complex dependencys in a singleton project?
inject IServiceScopeFactory, create your working scope, resolve your dispatcher and dispatch your command/query from there
Great as always !!!
I am checking your video after a long time and thanks for this lesson.
I have seen your NDC conference and came here to check what you have for us.
With regarding to coding style ,
If we have to refactor it by creating endpoint classes implementing Iendpoint interface and registering only the required services for the endpoint to maintain SINGLE RESPONSIBILITY
Then can we not also follow the same without using the minimal api way, using controllers?
Like only using the controller for specific endpoint?
Its there readymade, so why we need to take such approach and use minimal api ?
I think the real sauce for minimal APIs will be using them for service to service communication. I'd prolly just use a minimal api leveraging grpc comm between multiple services.
Some people don't seem to realize that the singe file approach is just a marketing tool. The ASP.NET team doesn't expect you to write your whole api in a single file...
WPF need your love ...
Hey nick, thanks for this video. The only thing missing is why did the minimal api get this much performence boost?
Can I request you reduce font by 1pt? I understand large text is useful for video, but if we can't see the all of the text, it's hard to understand. Witness 10:59, top of screen.
Great video!! Thanks Nick!!
Great video Nick!
Wow, what a great video!
Just amazing , thanks :)
nice video Nick
Hello Nick, great video.
I have the following question:
Why did you inject the endpoint definitions in line 24 from EndpointDefinitionExtensions?
It seems to be quite a nice change, but I don't know if rewriting existing big API projects, will be worth the effort.
Trouble I've found is that returning Task doesn't return TypedResults.... in Swagger for example you won't see the media type as "application/json" or the schema under Description.
Plans on making af video about NBomber?
Liked. While i disagree with the overabstraction as it is against the point of minimal apis, the performance you gain is something you can't ignore. Ofc i would like to see the "real" performance gain in production with lot of APIs/data.
PS: @all is unit testing important for minimal apis? do we really need it? if the project is that complex then maby we should use the classic way? idk...
"real performance gain in production" will mostly depend on external factors (database response time, external services, etc.)
Are you using a custom terminal program? How do you have tabs?
It’s Microsoft’s Terminal
This is faster because you are bypassing the ASP.NET MVC framework which is pretty bloated and comes with a perf cost.
I like the minimal APIs, it's very similar to Giraffe/Suave in F#. It's a perfectly good way to compose a large application together.
Bloated... compared to what? As a corporate developer/architect that's implemented every .NET web version since 1.0, I can tell you the benefits of a framework like MVC far outweighs any performance detriment, especially for junior devs.
The only time I would consider using this approach is for extremely light-weight POCs. But this will not scale when you teams of devs running sprints, and you need common framework components like audit, logging, authentication, authorisation, etc.
If you started at the mimimal point and added all the middleware stuff to get it all running .... you've just implemented MVC.
When you implemented authorisation policies, cross check bearer/auth tokens ( you are authN/authZ your API calls... yes? ), write to audit services, call DBs and other external service endpoints... any "bloat" from the MVC/Route pipelines will disappear.
This is been my experience with development large scale web applications ( '000s of concurrent users ) on .NET technology stacks over the past 20+ years.
@@robslaney3729 I think he was just explaining the performance difference between his 2 example projects.
@@robslaney3729 Not all web apis need all features. Even some "big" apis just need some authentication and go live.
Also not all companies follow strict processes. Even the companies who follow some "Scrum" guide have projects that need just to get shiped fast. My point is: minimal apis still viable solution.
Howver, i like your answer. People already started "how do i X, how do i Y with minimal apis...". I wish people don't end up "implementing MVC" as you said. For more complex apis or if your team is not happy with maintaining minimal apis, the just go classic apis.
@@shakeuk It was like 5k/30k performance gain. So a 20% performance gain WHICH IS AMAZING. However we must wait the final release of NET6 to see how classic apis will perform.
Also there are so many things to consider here:
- he is benchmarking on top AMD CPU with 12/24 ct(?)... when you propable don't even get the half of this power in cloud, and you scale via adding instances.
- what about some real world operations? efcore/databases/IO/authorization...
@@robslaney3729 Well it's bloated compared to ASP.NET. That's not to say if you need to leverage what the MVC framework has to offer and it makes your life easier, by all means, that's a judgement call you make. I obviously do not recommend re-inventing your own framework on top of Minimal APIs.
As a developer/architect myself, we have a lot of backend APIs that really are just LOTS of CRUD operations, or store and forward, or an entry point etc. There really is no need to over-engineer these kinds of APIs. The simplicity of Giraffe has been well suited to this and Minimal APIs I think are great fit here as well.
Juniors tend to copy what already exists in your codebase. If they see a structured example or are adding to a structured codebase, that is the pattern they will follow. In many ways Minimal APIs can lower the barrier to entry for juniors extending your APIs.
This seems like a really nice approach. Would you recommend this for someone building a new application over the standard HostBuilder approach?
When would you *not* recommend this approach?
I've been rebuilding my website with a Blazor WASM frontend and was looking to add an API to it, and was thinking about how I could make better use of generics and minimize boilerplate.
How do you annotate your endpoints with the new syntax?
Is that done using extension methods instead? E.g. auth attributes.
You can chain the RequireAuthorization or AllowAnonymous methods in a fluent fashion on the Map methods
@@nickchapsas But it will be possible to use attributes with final C# 10.
app.MapGet("/api/todos", [Authorize](TodoDbContext db) => (db.todos.ToListAsync());
Maybe you could do a minimal Api version with EF Core?
-im thinking about the stuff to do in the repositories and if you would do data validation and send back if properties are not valid or does not meet requirements. EF Core has the methods to create, post and delete objects so im not sure if i can skip the Repository part where you have GetById, Delete and Update because they already exist in EF Core
Woow!!! This is just awesome
Enterprise Applications means built by vendors and contractors maximize bloated and expense. You need at least 40 using statements.
Oh Wow, looks like express!
I do believe this could become even more powerfulll with source generators and it could resember the "Enterprise Way" of doing things :P
so if i want to inject my database and im using EF Core in my Rest Api Server, i would just have to replace your CustomerRepository in the DefineServices with ApplicationDbContext where i have all my DbSet methods?
Great approach, If you wanted to implement an exception filter with this minimal api approach, would it be possible??
is the final version of your code somewhere on a public github repo? Thanks!!!!!
Great video Nick - I've just started using minimal APIs but find the unit testing is sub-optimal. I'm using XUnit+Moq, but IResult is returning classes that are marked as internal (Results.Ok, Results.NoContent etc) making it much more tedious to test. Do you have a good solution for this without going via serialise / de-serialise cycle with mock classes?
They are actually fixing that in .NET 7 so give it a few months and it will fix itself. The alternative is custom extensions on the results
Does it work for Function apps or is there something similar to function apps?
Hey, what would you name the secretsauce folder in real life? I'm still confused about what should be called what.
This is just my opinion. I feel like minimal APIs are good for some cases like fast Prototyping, Mocking Services and of course real Microservices.
Imaging having an Azure Function, AWS Lambda or even a simple Container. This can lead not only a performance boost on your application but your entire development life cycle. Microservices in a single or minimum files means self-contain apps with minimum size, so you can build, test, release and deploy in less time. Once in production, that same small app can scale faster and I assuming that even have a better response after a cold start.
Minimal APIs are not just good or bad. All depends on the context of what you have, and what you need. We need to constantly change our point of view on how things are done. A well designed microservice architecture will be benefit of this approach. Can you imagine having a single file for each microservice like Customers, Sales, Providers, etc? This enables having even less effort for developers to understand, create, maintain services. Sure, this creates complexity outside the app itself.
As monolith architecture may not benefit in the same way as you expect to have everything in one entire solution.
Find the best that fits for your requirements and remember, sometimes the client or the business has the last word :P
Am wondering how you apply special attributes to those delegates like you would in a controller? Things like auth or swagger attributes etc
Ive been meaning to use this sort of stuff not for minimalism but for modularity/split between the module that has logic and any special hosting logic.
Also if you didn’t know if you brig up riders context action menu there is an extract interface button so you dont have to copy by hand :)
You can apply attributes to delegates now but you can also use the Fluent API approach and chain those methods, for example ".Produces(typeof(Customer))"
This is very interesting, I like the cleaner style. But, what about attributes for services like auth, or return response type info for swagger or such? Seems like that will make the app routing awkward. It'll look something like
app.MapGet("blabblah", [Authorize("Policy=Readonly")], [ProducesResponseType(500)] UpdateCustomer);
Not sure how that could be cleaned up. Multiple response types could add to the clutter. Not that it's any more code than the "old" way, but I like the minimal api direction/style, and hate it see if become less attractive due to attributes.
It's your lucky day, I just uploaded a video about that
@@nickchapsas thanks Nick!
can you do push notifications with minimal api?
2:10 You shouldn't have continued with the refactoring in a red state of error as you could be adding bugs to the code. This could have been a good way to demonstrate how to refactor a legacy application (aka, an application without unit tests) into a modern, maintainable application.
I’ve already done that in my 2 part refactoring exercise. This video isn’t refactoring but re-organisation but I called it refactoring because it’s easier to understand me click
It seems to me that this approach is kinda like nodejs with express router that accepts functions that are handlers
Well... That's better. What about multiple attributes (ex: Authorize, ApiVersion... etc)? Can we place their right into Map methods? Dunno.. This is a really good solution for PoC, I agree. What happens when we add all the necessary attributes and others elements just like in the big serious enterprise project? Yes.. this will be controller! %)
i thik this kind of solutions work very well with microservices, and a good api manager so you can leave authorization tasks and versioning to the api manager and focus only the task that needs to be done
@@hck1bloodday Hmmm... It makes sense. Thanks.
how to inject cancellationtoken in minimal api? IsCancellationRequested is always false even though i hit cancel in swagger
Thank you so much for this great video! So, is it recommended to use this approach for enterprise applications? Actually, I'm not so sure...
Define enterprise applications? It can mean so many things
@@nickchapsas well, I mean more complex projects rather than simple ones. If we are going to have a lot of endpoints with the different models,then thing will be getting complicated I guess. But with old-style approach everything stays fine.
@@hasan_shans I don't work with such projects so I can't give you the best advice there but the controller based approach would probably be better there. I only work on high scale/performance/throughput microservices, which Minimal APIs are a perfect fit for
Got it, thank you so much!
How do you put swagger documentation on to these minimal methods?
Either attributes or the fluent extension methods
How will you resolve Constructor based Dependency Injection in Minimal API.
For eg. in your code ICustomerRepository has to be passed as a parameter in every method of the class, unlike Controller based approach where we would add Dependency at Constructor level.
If we have multiple commonly used Dependenices e.g. MediateR, AutoMapper, ApDbContext then all of this needs to be passed in each method. Then how will you handle this?
You don't do constructure based DI in minimal APIs. You do Action based injection. If you want constructor based injection with minimal api tech then use FastEndpoints
Please do a video about designing a proper WebAPI project using modern C#.
Edit: My mistake, I just need to search back several years. For other readers, Nick has an entire course here: ua-cam.com/play/PLUOequmGnXxOgmSDWU7Tl6iQTsOtyjtwU.html
It covers only up to .NET 5, but I suspect changes are minimal as WebAPI is fairly mature.
Thanks for the amazing videos nick!. How can you require and endpoint to have a valid authentication token for example?
There is a video coming next week showing off Swagger, Authentication, Authorization and Validation so stay tuned for that
It looks very interesting, but also just like reinventing a bit faster controller with extra steps. GetAllCustomers/UpdateCustomer/DeleteCustomer - all in all we have the same methods defined both in EndpointDefinition and Controller. EndpointDefinition just has to implement an extra step to map internal methods to routes (which is done in controllers automatically or with route attributes) and injecting services (which anyway has to be done in both approaches, but there "controller" has to know about the implementation). As a result we have 13% higher performance (and maybe even higher as you said, but maybe lower if endpoint has comlicated logic) with extra infrastructure and a bit boilerplate code in "better controller". If application really needs this performance boost then yeah it makes sense, but in other cases it smells like overengineering.
I find controllers for APIs an anti pattern. The only reason they exist are because they just happened to be there when MVC came along and Microsoft rebranded them as WebAPI because they didn’t want to build a cleaner more focused version. The fact that a controller has N amount of method for actions that only loosely belong together is such a bit single responsibility violation
@@nickchapsas you call it antipattern, but still use it just in differently named class with extra methods from interface. What problem is to store unrelated methods in different controller? You can still define full route with attribute as you do it in Minimal API. The only advantage of your approach is a higher performance (which could become a deciding factor though).
Maybe the problem around controllers as WebApi is not in technology but in a long period of using them improperly which became a bad practice. In my opinion they are flexible enough to use them in correct way.
@@oleksandrnikonov8383 This video is largely outdated, and the update is the FastEndpoints video. Having a single class per endpoint structured in a vertical slice is a far better approach. I forgot I had the all the minimal api endpoints in a single class in this video.
@@nickchapsas Is there a follow-up video that shows the vertical slice approach?
4:40 Using an arbitrary type here on Program.cs line 5 seems fishy. The code looks like it is specifically doing something to the Customer class, but it could very well be doing those things for the entire assembly? If I'm tasked with adding a new model class to this application, it'd be quite confusing that I don't also need a line for whatever class I'm adding. I feel like it would be clearer if it was more explicit about taking an assembly by name rather than a class in that assembly.
Assembly scanning isn't a new concept. MediatR, Automapper, FluentAssertions and basically every other library does the same thing. It's up to the user to read the doc. A most common practice is to use what is called an "Assembly Marker" which is usually just an empty interface, but I didn't wanna dive into that in this video.
@@nickchapsas the Program class will be available in the next version when using top level statements
@@davidfowl Sweet. I was so confused the first time I drafted the video and I couldn't find it.
@Nick Chapsas Consider if the line was this instead:
builder.Services.AddEndpointDefinitionsFromAssembly(Assembly.GetAssembly(typeof(Customer)));
There would be no need to read the doc. It's slightly longer, but saves the tech debt.
@@KelvinNishikawa Naming is completely up to you. You can even go with services.AddEndpointDefinitionsFromAssemblyContaining(). Like I mention in the video, you should not treat whatever you see in this or any video as the de facto solution. Change things up to your own taste.
What about the other things we might take for granted like model validation? And the decorator 'apicontroller' which auto checks modelstate and returns a bad request etc. You didn't have that on your simple API, if it doesn't have that in or enabled, maybe that's why it's more performant, I could be wrong because I haven't checked the docs for all the features of the minimal API.
Additionally swashbuckle has additional decorators for enrich the openapi output, how would one use those with this approach without digging into the swashbuckle filters or writing custom secret sauce code to do that... Hopefully some new nuget packages will come out, but by the time u have done all that ... Won't you just have controllers again?
You can do all that in minimal api. Model parsing still happens in both of them since they parse the route parameter. Validation doesn't happen in any of them. For Swashbuckle you can simply use the fluent ".Produces()" methods. There are multiple blogs that showcase how to handle valiation in Minimal APIs. I don't think I've ever seen an app that actually goes to prod with the built in MVC model validation. Everyone replaces it for FluentValidation either with a Mediator pre processor or a middleware, which is possible in Minimal APIs too.
@@nickchapsas yes we use fluentvalidation as well since we don't like coupling validation to the models also fluentvalidation makes it really easy to write custom validation rules and unit test your model validation.
@@nickchapsas yes you may not have any validation in your sample projects but because you are using the typical middleware (including the apicontroller decorator) the aspnet core framework will still go through its pipeline which will include the modelstate check for every request. Your minimal API might not do in your example which could explain some of the performance gains... Again I could be wrong since I have not used the minimal API it dug into its features and or configurations.
I think should not return not found if not found data. Because same error code with case not found url.
In REST APIs, 404 means resource not found
Hey Nick, thanks for great content!
One question...Is it possible to combine classic controllers and minimal api and if so: do we get the same performance benefit when we hit endpoints implemented using minimal api within such combined solution?
Yes you can combine both but controllers lose the performance benefit even when combined with minimal APIs
@@nickchapsas actually i am more interested in the opposite case: do minimal api endpoints still gain performance benefits even when they are within the solution where classic controllers are used as well?
@@nickchapsas just a bit of a background... i have a project in which i have dozen of controllers which are not performance critical and for which i definitely have benefits of their well established infrastructure/ceremony. at the same time, i have 2 particular endpoints which get unsymmetrically more load. so, if i could get benefit in implementing just those 2 endpoints using minimal api, that would actually be 15% for free which would be awesome.
I have not tested that actually. I’ll give it a go tomorrow and let you know
Why do you need to make an interface for the repository? I don't understand how that makes it testable, could you explain?
Not the repository must be testable, but the service using it. For that purpose you can provide different repository, that will provide test data.
@@ZeVS777 Can't you just use the type of the class?
@@donnyroufs551 you can have two repositories, that implement the same interface, but one is reading dats from real db and the second you write for specifically return test data. Than you can create instance of your service, but provide test repository for it, so you can test your service without any interaction with DB. You can't do these things in another way without duplicating business logic. You can write the same business class with the same logic, of course, but than you must always bring the changes from your real class to test class. This would be a mess.
@@ZeVS777 So you can't use an existing class implementation as a type to create a mock or stub in c#?
@@donnyroufs551 short answer you can't. It is a big theme: unit testing. I recommend watching videos about it and/or read books about it. Unit testing is chained with dependency injection, so search for this term too. And just try it yourself, practicing and mistakes are the best teachers.
how about, is this a good way to used in programming?
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.CompilerServices;
I have subscribed to your channel for about 2 months, but I still don't have a roadmap to get started on how to learn C# .Net, can you guide me a bit. Thank you very much.
P/s: sorry I used gg to translate
In reviewing this I do see that Nick has shown an alternate method of defining API's, but is not clear what the advantage to this is. There is still quite a bit of secret sauce being implemented all of which hides this and that....but overall not clear what is the actual purpose/advantage of this over just doing the standard method? "Simpler" seems like a misnomer as is hides much of the mechanics and that is not actually simpler. Please Nick do not take this as a criticism of your video, your thoughts are always appreciated. Just my thinking as developers change in and out of our teams, seems like simpler remains the most obvious way.
How does this play with custom middlewares?
You can have middlewares in the same way as before
Hi Nick! Awesome video. Could you please show EndpointDefinitionExtensions.cs line 14 as a whole since it is not shown on the video at 11:00? Thanks!
Most probably "!x.IsInterface && !x.IsAbstract"
Similar to what is being done here ua-cam.com/video/_YkvFQ1-Lt0/v-deo.html
i think is ".Where(x => typeof(IEndpointDefinition).IsAssignableFrom(x) && !x.IsInterface)"
🔥🔥🔥
Cool.
Just 4 minutes in, but doesn't putting all the endpoints in a single class basically mean you're creating an oversized controller?
It feels like you invented controllers again to handle the issues that were broached. To avoid the bloating issue, use endpoint definitions (controllers), to make it more testable you created methods for the delegates. There are issues with this home grown approach though, how do we avoid registering the same service multiple times if you have different endpoints in different files requiring the same object (e.g. customer repo). I believe minimal apis are not a drop in replacement for controllers but more for prototyping, simple use cases.
I'm not impressed with the load testing performed, I assume there would be some gains with minimal api because controllers are scoped per request (meaning they get created and GCed), while minimal api delegates are essentially singletons. Would need a more complex example like doing some IO and not completely in memory to measure the realistic gains.
I do enjoy the ability to use minimal apis and the flex .net 6/c# gives me between prototyping and full fledge development. Just my two cents.
Many false things in this comment so let’s clear some things up. First, no I didn’t reinvent controllers. This is the REPL pattern implementation, completely different from MVC, which is where controllers come from. The key here being that one handlers belongs to one request and has one specific response. Yes this is different, also no, you don’t have to worry about the same service twice because you should be using the TryAdd alternatives to DI, not the Add ones. When you are adding any package you don’t know what they are registering internally and if you don’t use TryAdd you end up with the same issue. Minimal APIs shine both in simpleuscases and also micro services due to the simplicity of microservices by nature. Also no they are not faster because they are singletons. In fact, they are scoped exactly as the controller ones. They are faster because they don’t use a lot of filters and middleware the controllers automatically use but you don’t need. It’s a remnant of the MVC world which was repurposed mostly. Memory is less and method jumps are less so they end up faster.
great video, you're a great programmer..
performance is indeed impressive, but, sorry man, it isn't minimal anymore...
sweet
Why is this limited to APIs? Why couldn't you build an entire website like this: app.Map("/", async (context) => {await context.Response.WriteAsync("...Example Page Output");});
Can you put it on 1 line :))
Well - I'm not a big fan of this minimal apis, but:
If we combine it with CQRS, it could be a really nice option.
With nice extension methods (like "MapQuery" or "MapCommand"), that just use the minimal api methods, we can have all endpoinds in one single and easy to understand file.
And then we have the advantage of minimal APIs and no additional overhead in a controller that only calls the mediator.
This could be a realy nice way to create web apis with CQRS.
can i get a source code?
Source code is available to my patrons
I like you Nick