I have always thought that mappers should be something that framework should do automatically, and just in case you need something special, you can override the behavior. Most of cases you have lots of entities with 90% of field names exactly the same...
I agree with your assessment 100%: I like the idea of this library in general, I think the property injection is a very weird and outdated choice for dependency resolution, and I like the opportunity to organize my APIs into vertical slices by feature instead of layers by function. I wonder if this library would be open to a pull request or two?
Except for the DI approach here I like it. Especially, I don‘t have to use MediatR, add a custom pipeline behavior for validation and keep FluentValidation and MediatR up-to-date. Edit: I just saw that they implemented constructor injection! I‘ll give it a shot.
Thanks for your video. I have the same reproach for dependency injection. Furthermore, the configure method may accept a builder in argument instead of defining endpoints informations with protected methods to enforce configuration.
ctor injection has been added. i'm curios what purpose does accepting a builder argument in the configure method serve in your pov? my thinking is that the configure method can be nicely collapsed away until you need to see what the setup of a particular endpoint is. out of view, unmangled with the handler method, which in mvc controllers i absolutely loathe :-)
Hello, This is a huge improvement for ctor injection and the main relevant point. 👍. The interests of builder are the following points : - avoid using configuration methods in ctor or in handle/handleAsync method. - enhance your API with more discoverability and separations of code. - the builder can enforce some confugurations such as verb and route. Example : public IEndpointConfiguration Condigure(IEndpointConfigBuilder builder) { return builder .OnVerb(HTTP.Post) .OnRoute("...") .Create(); } PS : sorry in advance for my poor english.
The lack of attributes is so slick. I loved attributes and reflection when I first started using C#, but I have since changed my mind. Attributes represent non-debuggable code (or at least barely debuggable). The Configure method is such an elegant design.
the configure method is not an original idea though. the inspiration for it came from how fluentvalidations does it's setup in the constructor. with fastendpoints, the constructor was not ideal for it as the ctor would be run everytime an endpoint would be instantiated (on each request). configure method is only ever run once during app startup.
What exactly are you going to debug in attributes? There is no logic. Also, what are you going to debug in Configure method? There are basically initialisations.
Hi Nick. Thanks for a great presentation! I just started to build a new version of our API with FastEndpoints. It's very easy and nice to use! But one thing I wonder about when it comes to using the ResponseMapper. You show a very simple mapping from an entity to a response. But how do I use it to map to a more complex response with lists of sub entities in an entity? Do you instead recommend to map more complex types with Mapperly?
In this case you’d need to do something quite a bit different for the library to be a restriction. But hey, that’s the whole point. You can learn the Minimal API tech that it’s built on top of and structure it any way you want
@@nickchapsas "In this case you’d need to do something quite a bit different for the library to be a restriction." Well then surely it's not opinionated, is it?
I am switching to this for our new APIs. The request/response/endpoint structure will make code so much easier to navigate. Much like what I am used to from GraphQL.
I appreciate it when libraries are opinionated, but the DI implementation is very iffy. DI has been "solved" in .Net imo, so stick to that pattern. Additionally, the `Configuration` method has a weird structure. `Verbs` method call in particular urked me
Ah good old days of property injection. I remember using it in 2010 with spring. There is literally no objective reason to use minimal APIs except for the performance gains. Additionally the library looks very clunky. There is nothing minimal about it.
@@nickchapsas I don't see that a follow-up design review video got posted. I would love to see that. We are evaluating FastEndpoints for our next project.
After watching your API Endpoints video, it was a great start but felt like it relied a ton on MediatR and traditional patterns to build out. I found Fast Endpoints and Carter around the same time. Fast Endpoints really cleans things up. The ceremony is still uncomfortable but better than most options. But it did allow me to get to my destination for enterprise level dynamic code generation much faster
Right so if you lock in certain constraints, you can automate code generation and make an sdk around a construct. In my case, I prefer to use CQRS to keep the use case in the language of the business. if my endpoint is matched to a command or query, and I can model it in yaml, as well as data shape, to build handlers, dtos, validators, etc. Source generators fall short IMO but tools like Scriban/Textrude and Yellicode help turn configuration into code. Then you can bake in all sorts of patterns like OAS, resilience, logging, telemetry, caching etc in common ways without writing the code. Fast Endpoints was a means to that end for me.
I actually think Steve Smith, the guy that wrote and published the endpoints library says it eliminates the need for Mediatr. (that said, not sure why all of a sudden everyone is slamming mediatr. It allows for very clean enpoints, whether they are controllers, or minimal API, or carter, or whatever).
@@pilotboba right?! MediatR is a great tool. I think it just comes down to preferences and optimizations. Where API Endpoints sort of left me hanging was it was well setup for Endpoints but not necessarily vertical slicing and enterprise robustness. That's where Fast Endpoints sold me, it brings in opinions that I value and a system of constraints that encourage vertical slicing. It's not a perfect solution though. The opinions in code are not always the most intuitive (screaming architecture) or follow traditional patterns. Either way, both frameworks bring value, just depends on preferences
Nice video with some good points. I'm very curious about the 2nd video. The author released version 3.7 with support for constructor DI. Sidenote: I'd suggest REPR to be pronounced REaPeR ;)
I know it’s pronounced reaper but REPRRRR is funnier 😂. Also yeah DI was one of the points of the next video. I still have several others but I will probably reshoot it or end up opening an issue on the GitHub repo with all my suggestions
Once I read "fast" in the name of the library, I expected to prove of it till the end of the video. It would be intresting to see if it's really fast in opposite to standard controller-based approach.
They have a very detailed dedicated section on their website. It would be pointless to run load tests since they already have all that on their site. They are as fast as minimal APIs which is as fast as we can get
Thanks Nick! What is by your opinion best library to use in order to separate Endpoints like this? Since i Saw another video of you showing another library similar to this. Thanks!
So this library in my opinion is better because it is built on minimal api technology. It is faster and it has more functionality out of the box. I recommend this one
Tried implementing it in an ongoing project, but, there are a lot of stuff missing still, so, it will be worth checking out later on, but, for now, I think that it would take a lot of effor to make it work in my case. Also, I think its not production ready yet. Thanks for the insights tough!
You can unit test them like any other class, you just have to be careful with instantiating the properties that normally would come from constructor injection. In regards to auth, there is a dedicated and detailed section in their docs
Another good one Nick! Thanks for posting. Regarding the choice of DI, someone asked on their discord server and the following is the reply form the author: "ok here's my thinking on this matter. the endpoint classes are never meant to be new'ed up by anything or anybody else other than the library itself. so there's no real point in dirtying up the user's code with a constructor that has many arguments and then assigning it to a private variable. it's just redundant code imho. on the otherhand if this was a class that's going to be referenced from multiple places in a user's codebase, then definitely i would've implemented standard constructor injection."
That’s not true. They are meant to be newed up by the tests that wanna pass down mocked dependencies. It is also unfortunate that if I happen to have a property with the same type of something that is already in DI then things will break. Last but not least, it doesn’t follow any of the other known and well understood approaches such as constructor injection or InjectAttribute based injection. I have a lot of problems with the library’s design and I have a dedicated video on that coming
@@nickchapsas Looking forward to that video. In a previous instance he mentioned that Minimal Apis nor FastEndpoints can be properly "unit tested" if it touches something from the HttpContext without mocking the context also. So he/she recommended doing WAF testing only. If that's correct, doesn't that mean you register mock services/dependancies in the WAF factory instead of constructing the classes yourself via the constructor?
Any advice or suggestions on how to share the Request/Response classes for the features with some sort of front end project like blazor without recreating classes or duplicating code. Trying to come up with a good architecture and combine projects in one solution with the blazor project, a shared class library project and the fastendpoints minimal API project. The shared class library project would hold DTO classes. Would love to hear how others are structuring when using fastendpoints minimal api. Thanks all.
1. What is the difference between the Ardalis implementation and the FastEndpoints implementation? They seem rather similar, adressing basically the same problem. Is it simply an implementation preference? 2. In your latest clean minimal api github repo you are not using the FastEndpoints mapper. Again, is it a personal preference to not overcomplicate things? Awesome content Nick, much appreciated!
1. The Ardalis one is based on controllers. FastEndpoints are based on minimal APIs, which makes them more efficient. Conceptually are the same idea but the FastEndpoints approach is based on the new tech. 2. I am using FastEndpoints in that repo
Hey, great video. Combined with the one from NDC Oslo this is so good. A bit off topic, but in your videos, your keyboard is very silent, so interested to know which keyboard you're using :). Keep up the good work
Hi Nick, your videos are super. Just want to check in your website - if we buy essentials package, minimal apis are not included - will you give that as present or we need to buy that separately? Thanks and keep up excellent work.
Hey Mehdi. Bundles are logical groupings and I don't consider the Minimal API course part of that bundle. When more API related courses are added they will be in a separate bundle but there is no plan to add it in any bundle right now. it has to be purchased separately.
Honetstly, don't understand why it is better than controllers. If I have some CRUD, I can have 1 controller, explicitly inject services without property magic, specify routes and stuff with attributes in elegant way. Here I need to have a class with two methods for 1 endpoint. What problem does it actually solve?
Controllers by definition violate SOLID. Both single responsibility and open closed are fundamentally violated. With this approach you simply have a 1:1 relationship to a single endpoint. Not injected services that aren’t needed, no performance impact with action filters or middleware that isn’t needed. Need a new endpoint? Create new handler. Don’t need it anymore? Delete the endpoint. Need to change something? You only change that single class. It is by definition better but the problem is that .NET devs are so used to MVC that can’t see anything else as a viable option
@@PelFox YT doesn't let me post links. Go to the doc site and click on the left menu where it says "Swagger Support". It's the 4th headline from the top. There's a method called Summary() for describing the endpoint and you can write XML comments on DTOs.
To my untrained eye this library looks like the same features of minimal API in NET 6 just structured differently. Perhaps I just haven't worked with minimal API enough, but I think it has all the same capabilities in a syntax that is equivalent in complexity and extensibility. I don't see the added value. Would have been nice if the video did a bit of compare and contrast so I could understand what's better over the standard functionality.
Structure is everything. Using node’s express library, you can structure your api in hundreds of different ways. That doesn’t mean that everyone using node can build a well structured api with express. This is what this library does best. It sets you up in a well designed structured way with tools that you will almost certainly use. To phrase it a bit different, everyone has seen the Mona Lisa and everyone everyone can get paint, brushes and a canvas, but not everyone can use them to paint the Mona Lisa. It’s the same thing with programming
Hymm... I don't program any web at all so all this stuff seem exotic too me. It also don't look minimalistic to me. For example I'm struggling to figure out the benefit of this base "Mapper" class. Since all this is static already you could just simply create something like this: public static class Map { public static WheaterForecastRequest FromEntity(WeatherForecast e) => new WheaterForecastRequest { ... } } and still end up with the same Forecasts = forecast.Select(Map.FromeEntity); So what is the purpose of all this extra work? The only benefit I see is that you can jump to the 'FromEntity' function straight from the Endpoint's signature but I don't think such thing is a good trade, considering all the obfuscating boilerplate...
Hey there. I am taking your minimal API course on teachable and it's great so far, but I am trying to figure out how to reduce request validation boilerplate code in my endpoint handlers. You mention in it, as well as I believe another video of yours on minimal API that you can extract it out into middleware, but I am having a hard time figuring out how? I always used filters in MVC but now since it is not possible in minimal API, I would like to learn how to roll my own pipeline. Can you do a video explaining? thanks for the great content.
Hey there. So currently, there is no "Generic" way to do it on the API level. You really have 2 options. Either plug in MediatR and use a Pipeline filter which I show here: ua-cam.com/video/2JzQuIvxIqk/v-deo.html or if performance doesn't matter to you you can "cheat" your way into validation with this example: github.com/Elfocrash/DotnetDocsShow.MinimalApis/tree/main/DotnetDocsShow.Extensions.Validation The .NET team will add filter in .NET 7 so there will be a way better way to deal with validation and the course will be updated. I didn't wanna add a solution in that isn't as performant and will be obsolete 8 months after the course
@@nickchapsas Thank you. yes I was hoping to avoid mediatr if possible because I have already implemented your very useful assembly scanning technique for endpoint registration, but the validation logic just adds so much bloat to my otherwise nice and thin endpoints that I may install it just for the validation.
Hey Nick! How is it going? I really really liked this video and I tried to implement something myself using fastendponts, but I found that this tool is really great to build very simple APIs... When you need an API that does the CRUD, for example, the best would you use the Microsoft Default tools. Maybe in the future, when FastEndpoints get more mature, it would be a good substitute to the Microsoft's default... What do you think?
FastEndpoints are very good for simple and complicated APIs. I build high performance microservices that aren’t that simple and I didn’t have any problem with FastEndpoints. Here is a REST API for example: github.com/Elfocrash/clean-minimal-api
I reviewed this project after watching your video. It looked quite reasonable, implicit property injection and all. For me the deal breaker is the fact that is locks the application logic into the protocol. How would I use this outside of an HTTP request? This feels like Mediatr trapped inside the protocol. I'll stick with Mediatr. Thanks for the video.
ctor injection has been added. also even though the main use-case is rest api building, you can make an endpoint class just take in a request dto, do some handling and return a response dto. check the unit testing page on the doc site. there's a "public override Task ExecuteAsync(RequestDto req, CancellationToken ct)" you can use. but gotta take a bit of extra care not to touch any http related convenience methods/properties supplied by the base class and inject via the constructor everything needed to handle the request.
@@nickchapsas we have this thing at work if someone mentions mediatr or automapper that person has to buy lunch for the whole team for a full week lol :p
@@nickchapsas beside mediatr subject, having the logic in the protocol doesn't sounds right if you want to expose the same servive by different means (web api, grpc) or use it straight into a dekstop app. Having the logic in the business/application layer (thinking about Clean Application) allows you to reuse everything and just consume the Command/Queries into the UI of choice: In this regard, I don't think that having a mediator (note I'm not talking about the mediatr library) is a bad choice, it allows you to decouple things. This library maybe could be used to have a declarative endpoint that uses minimal API and do its own mapping stuff but internally it could still make use of a mediator code to handle validation, transactional behaviors, loggings and so on on specific command/queries.
Property injection is an anti pattern because how am I supposed to know it's a dependency when newing up the object. Constructor injection is the only way
@@nickchapsas still it's property injection. I don't think I'll be using this because of property injection anti pattern. I love this idea though. They just need to fix that
How to use RoutePrefix=string.Empty; In swagger i unable to launched by default index.html page in azure as well as in vs code can someone pls help me for the same
9:35 looks like now we can use the constructor to inject. I tried this ( and worked: sealed class ProtectedEndpoint : EndpointWithoutRequest { private readonly IPermissionFilterFactory _filterFactory; private readonly ILogger _logger; public ProtectedEndpoint(IPermissionFilterFactory filterFactory, ILogger logger) { _filterFactory = filterFactory; _logger = logger; } // .. continue }
The idea of the library is great. I truly think that the .NET community will go in that direction regarding Minimal APIs Endpoint/Controller structures. Seems strange that dependency injection is done by initiating a field instead of having this dependency being injected from the constructor. This opens the posibiliy to have a instance of the endpoint class with it's dependencies being null, that's not good and shouldn't be allowed IMO.
Hey Nick love your channel and your content, but could you do if its possible ofc pricing for different reasons, I'm I'm Brazil so GBP is very expansier than BRL haha in anyway keep coding
I'm not a fan of all the implied behaviours. For example, it took me a bit to understand how the route parameter was being added into the request. I assume it was mapping it to the same named attribute in the request but then within swagger you could see that concept trip up when the route parameter and the request parameter was shown. It is unclear what happens if you supply a body with the same shape, does it get overwritten? This is one thing I like from the controller approach is the attributes specifying parameters of the method with [FromBody] and [FromRoute]. It just makes it so much clearer and explicit.
I don't see so much added value here. My expectation is: I create a relational model with a couple of entities and relations, constraints, etc. Then I get a tool that takes all this and creates a structured API for me with all the good stuff: authentication, access control, roles, CRUD, read with a query support similar to OData / GraphQL, DB contraints reflected in C# code, validation handlers I can implement for the very special stuff, etc. All that pluming code is really boring. We used to have this in the past from MS. It was called LightSwitch. It even supported generating structured default UI implementations. If you need to fiddle around with 5 classes plus 3 interfaces for each entity to implement it, something is wrong. It is repetitive work. The effort you have to spend, to do all this manually is hardly ever worth it. You need a BIG business case to pay a SW developer to spend 3-5 days to implement CRUD for one entity.
You should look up Vertical Slice Architecture and why it's actually superior to N-layering. I too had a hard time initially with the concept of putting domain logic in the handlers. What I've found is that there's really no need for an extra layer of abstraction unless you need the business logic to be portable and it needs to be referenced from multiple different projects. Also ultimately there is no presentation layer when building Web APIs. There is always only a Request > Handling Logic > a Response.
Sure, why not. It really depends on how those endpoints are organised. Are you doing vertical slices and splitting by feature? No problem at all. At that size I would simply split this service to smaller ones but it’s totally doable
What I don’t really like is that you put routes very far from the request classes. That leads to errors that cannot be simply eyed out or warned about with compiler/ide.
I have been watching this project for a long time. The idea is good, but the implementation in some places is not perfect, in my opinion. For example, dependency injection at the endpoint is not implemented in the best way. It was also strange for me to see the contents of method "Configured" not in a fluid style. Although the project is developing and improving swiftly, so I believe that many changes are still ahead.
I agree with you 100%. I actually have a video coming in a week, talking people through why I think the design of the library isn’t great. I think it does a lot of things right but it deviates quite a bit from the general .NET “familiarity” that such projects should have
Hi Nick, the Minimal15 coupon is not working for me, the page says that is invalid, please could you check it? I'm a brazilian developer and the discount will help me a lot.
Tried Minimal API, but calling vendor only supported XML and that’s not available in Minimal. At least, I couldn’t figure it out. That’s pretty opinionated.
This library is just one opinionated implementation. If you don’t want to know the inner workings or how you can create something that fits your own needs, then you probably don’t need to no. If you are planning to get the most out of minimal APIs though then you might want to take it.
So instead of using Controllers, let's scale back and create structureless request handlers in the form of Minimal APIs so that we can add structure back with lots more boilerplate. Win I guess? I genuinely don't get the appeal of Minimal APIs and this kind of library further compounds my confusion.
Controllers come with a lot of useless middleware that is a remnant of MVC. I find controllers a really odd structure and I never liked them. Minimal APIs allow me to fully control the request pipeline and structure as I want it exactly. That’s the appeal. I guess if you don’t wanna think about it too much and just build something, then controllers are fine. If you wanna be more flexible with your solution, then minimal APIs are great
I don’t like that the API can return something that is not in a single part of code where the API is defined. This would be a mess with applications with hundreds of APIs
And would be bad from a code review perspective. Code should be optimized for the reader/code reviewer not the writer and this pattern adds confusion to the reader
It is one of my problems with the design. Stay tuned for Thursdays video where I talk about that in detail. I think it’s very fixable and the creator has proven to take feedback very well, with constructor dependency injection already implemented
@@nickchapsas Did this video come out? I've discovered your channel recently and I've been literally devouring the content (This is the type of content I believe I really missed on my way from regular to senior dev). I got very interested in the subject and would love to hear more critique/see the video where you try to fix the issues you see here.
It's a shame they focus so much on minimal API IMO. It's not feature complete. Everything needs hacks to work. And who asked for it? The normal API is much better and easy to setup
Is it though? Or are you just used to it? Because I’ve thought the same thing until I asked people without api experience and all of them found minimal APIs easier to use. The 2 features that they didn’t have were form files and filters. We are getting both in .NET 7. I don’t see a world where I build a new api with anything but minimal APIs. I would be leaving a lot of performance on the table too.
@@nickchapsas I like when things are declared and explicit. I don't like too much magic going on behind the scenes. I don't like it's more difficult to tweak, just to make the template as small as possible. No versioning support yet. I also don't like the new Program.cs file that leaves out namespace, class name, etc. Where are the args[] parameter coming from? Magic. I feel this is a trend. And it goes against what makes C# nice. Explicit and strict language, that does what it says.
I dont quite like the fact that http verbs are slipping through to my handler logic (e.g. business logic). something that combines source generator with Mediator request/response would be the ultimate goal.
I was excited for this video but am very disappointed in the amount of ceremony required to do something so simple. Why not use attributes for request methods? Why not use method name for endpoint route? Why not use method parameter types for mapping data? Seems like belt and suspenders to me.. very typical of C# and the main reason why so many developers have moved to other ecosystems.
The only thing I disagree with is the method name. It is very very dangerous to leave it up to the method name to determine the route. It could definitely be better which is why I made the video. So more people can see it, then the author can see the reaction and try to address it. Or simply someone else forks it and they make their own
Yeah I wish they simply used the generic T type to return it instead of using Send. You can have double send or no send at all and the code will still compile.
I hate the term “API”. It’s way too vague and overused. Wish we could come up with terms that were more specific to what we were taking about. Hell Web API or REST API would even be better than just API alone, yet there are entire companies named around this acronym.
I downloaded you Github repository for this but it seems that lots have changed in FastEndpoints. I had to update the packages but I still got the error that there is no "ErrorResponseBuilder" app.UseFastEndpoints(x => { x.ErrorResponseBuilder = (failures, _) => { return new ValidationFailureResponse { Errors = failures.Select(y => y.ErrorMessage).ToList() }; }; });
Take a shot every time Nick says "here we go"
Please don't you will die
I discovered this a couple of months back and it's really my favorite way to build API:s in .NET right now.
The more I watch Nick, the more I feel we need a "Here we go!" t-shirt in the store!
I have always thought that mappers should be something that framework should do automatically, and just in case you need something special, you can override the behavior.
Most of cases you have lots of entities with 90% of field names exactly the same...
This is a hill I will also die on.
I agree with your assessment 100%: I like the idea of this library in general, I think the property injection is a very weird and outdated choice for dependency resolution, and I like the opportunity to organize my APIs into vertical slices by feature instead of layers by function. I wonder if this library would be open to a pull request or two?
They are very active and they even have a discord server
In the mean time today the functionality for constructor injection was added to the library
@@flightdecksoftware Are yo ujoking, how was this added in the past day?
@@sunefred - Not joking. They were listening, and made a change fast. It's awesome.
@@BigPoleTightHole lol yeah. everything about fastendpoints should be fast ;-)
Awesome! Just bought your course bundle. Enjoying it a lot. Thanks.
Except for the DI approach here I like it. Especially, I don‘t have to use MediatR, add a custom pipeline behavior for validation and keep FluentValidation and MediatR up-to-date.
Edit: I just saw that they implemented constructor injection! I‘ll give it a shot.
Very nice project, thanks for letting us discover it!
FasEndpoints is a brilliant approach. Wouldn't it be a good idea to also make a video on how to unit test those things?
As always, great video, thanks!
Thanks for your video.
I have the same reproach for dependency injection. Furthermore, the configure method may accept a builder in argument instead of defining endpoints informations with protected methods to enforce configuration.
ctor injection has been added. i'm curios what purpose does accepting a builder argument in the configure method serve in your pov? my thinking is that the configure method can be nicely collapsed away until you need to see what the setup of a particular endpoint is. out of view, unmangled with the handler method, which in mvc controllers i absolutely loathe :-)
Hello,
This is a huge improvement for ctor injection and the main relevant point. 👍.
The interests of builder are the following points :
- avoid using configuration methods in ctor or in handle/handleAsync method.
- enhance your API with more discoverability and separations of code.
- the builder can enforce some confugurations such as verb and route.
Example :
public IEndpointConfiguration Condigure(IEndpointConfigBuilder builder) {
return builder
.OnVerb(HTTP.Post)
.OnRoute("...")
.Create();
}
PS : sorry in advance for my poor english.
Nice content as usual, Nick!
Thanks for your video.
Could you please make a tutorial for GraphQL and the best libraries to make it easy to deal with?
Thank you, Nick, Very useful video.
Should I integrate FastEndpoint with CQRS ?
Thanks, I really like this library. Definitely gonna use it in my next project!
The lack of attributes is so slick. I loved attributes and reflection when I first started using C#, but I have since changed my mind. Attributes represent non-debuggable code (or at least barely debuggable). The Configure method is such an elegant design.
the configure method is not an original idea though. the inspiration for it came from how fluentvalidations does it's setup in the constructor. with fastendpoints, the constructor was not ideal for it as the ctor would be run everytime an endpoint would be instantiated (on each request). configure method is only ever run once during app startup.
What exactly are you going to debug in attributes? There is no logic. Also, what are you going to debug in Configure method? There are basically initialisations.
Hi Nick. Thanks for a great presentation! I just started to build a new version of our API with FastEndpoints. It's very easy and nice to use! But one thing I wonder about when it comes to using the ResponseMapper. You show a very simple mapping from an entity to a response. But how do I use it to map to a more complex response with lists of sub entities in an entity? Do you instead recommend to map more complex types with Mapperly?
Being highly opinionated is good right up until you need to do something slightly differently.
Which is almost all the time.
I was waiting for this video.
In this case you’d need to do something quite a bit different for the library to be a restriction. But hey, that’s the whole point. You can learn the Minimal API tech that it’s built on top of and structure it any way you want
@@nickchapsas "In this case you’d need to do something quite a bit different for the library to be a restriction."
Well then surely it's not opinionated, is it?
I am switching to this for our new APIs. The request/response/endpoint structure will make code so much easier to navigate. Much like what I am used to from GraphQL.
Absolutely brilliant! Thanks for sharing this!
I appreciate it when libraries are opinionated, but the DI implementation is very iffy.
DI has been "solved" in .Net imo, so stick to that pattern.
Additionally, the `Configuration` method has a weird structure. `Verbs` method call in particular urked me
Ah good old days of property injection. I remember using it in 2010 with spring. There is literally no objective reason to use minimal APIs except for the performance gains. Additionally the library looks very clunky. There is nothing minimal about it.
You gonna love my design review video coming next Thursday then. I talk about all that in detail
@@nickchapsas I don't see that a follow-up design review video got posted. I would love to see that. We are evaluating FastEndpoints for our next project.
After watching your API Endpoints video, it was a great start but felt like it relied a ton on MediatR and traditional patterns to build out. I found Fast Endpoints and Carter around the same time. Fast Endpoints really cleans things up. The ceremony is still uncomfortable but better than most options. But it did allow me to get to my destination for enterprise level dynamic code generation much faster
Could you explain what you mean by dynamic code generation? Sounds intriguing 😃
Right so if you lock in certain constraints, you can automate code generation and make an sdk around a construct. In my case, I prefer to use CQRS to keep the use case in the language of the business. if my endpoint is matched to a command or query, and I can model it in yaml, as well as data shape, to build handlers, dtos, validators, etc. Source generators fall short IMO but tools like Scriban/Textrude and Yellicode help turn configuration into code. Then you can bake in all sorts of patterns like OAS, resilience, logging, telemetry, caching etc in common ways without writing the code. Fast Endpoints was a means to that end for me.
@@DanielMPries Very interesting indeed. Need to look in to those tools you mentioned. Thank you!
I actually think Steve Smith, the guy that wrote and published the endpoints library says it eliminates the need for Mediatr.
(that said, not sure why all of a sudden everyone is slamming mediatr. It allows for very clean enpoints, whether they are controllers, or minimal API, or carter, or whatever).
@@pilotboba right?! MediatR is a great tool. I think it just comes down to preferences and optimizations. Where API Endpoints sort of left me hanging was it was well setup for Endpoints but not necessarily vertical slicing and enterprise robustness. That's where Fast Endpoints sold me, it brings in opinions that I value and a system of constraints that encourage vertical slicing. It's not a perfect solution though. The opinions in code are not always the most intuitive (screaming architecture) or follow traditional patterns. Either way, both frameworks bring value, just depends on preferences
Nice video with some good points. I'm very curious about the 2nd video. The author released version 3.7 with support for constructor DI.
Sidenote: I'd suggest REPR to be pronounced REaPeR ;)
I know it’s pronounced reaper but REPRRRR is funnier 😂. Also yeah DI was one of the points of the next video. I still have several others but I will probably reshoot it or end up opening an issue on the GitHub repo with all my suggestions
I think I just fall for u after ur joke of REPR XD.... ❤️❤️😸 Nice smile 😘
REPRRRRRRRRRRR
Once I read "fast" in the name of the library, I expected to prove of it till the end of the video. It would be intresting to see if it's really fast in opposite to standard controller-based approach.
They have benchmark results posted on the website.
They have a very detailed dedicated section on their website. It would be pointless to run load tests since they already have all that on their site. They are as fast as minimal APIs which is as fast as we can get
Thank you for your great videos.
Thanks Nick!
What is by your opinion best library to use in order to separate Endpoints like this? Since i Saw another video of you showing another library similar to this.
Thanks!
So this library in my opinion is better because it is built on minimal api technology. It is faster and it has more functionality out of the box. I recommend this one
@@nickchapsas awesome, thanks for the reply, will definetly check it out!
Tried implementing it in an ongoing project, but, there are a lot of stuff missing still, so, it will be worth checking out later on, but, for now, I think that it would take a lot of effor to make it work in my case. Also, I think its not production ready yet.
Thanks for the insights tough!
Huge fan.... What abt Authorization and unit test in this case ?
You can unit test them like any other class, you just have to be careful with instantiating the properties that normally would come from constructor injection. In regards to auth, there is a dedicated and detailed section in their docs
I'm building APIs in NodeJS (Fastify) and this seems familiar. 🙂
This lib is good, but as you mentioned, DI should be explicit.
Another good one Nick! Thanks for posting. Regarding the choice of DI, someone asked on their discord server and the following is the reply form the author:
"ok here's my thinking on this matter. the endpoint classes are never meant to be new'ed up by anything or anybody else other than the library itself. so there's no real point in dirtying up the user's code with a constructor that has many arguments and then assigning it to a private variable. it's just redundant code imho. on the otherhand if this was a class that's going to be referenced from multiple places in a user's codebase, then definitely i would've implemented standard constructor injection."
That’s not true. They are meant to be newed up by the tests that wanna pass down mocked dependencies. It is also unfortunate that if I happen to have a property with the same type of something that is already in DI then things will break. Last but not least, it doesn’t follow any of the other known and well understood approaches such as constructor injection or InjectAttribute based injection. I have a lot of problems with the library’s design and I have a dedicated video on that coming
@@nickchapsas Looking forward to that video. In a previous instance he mentioned that Minimal Apis nor FastEndpoints can be properly "unit tested" if it touches something from the HttpContext without mocking the context also. So he/she recommended doing WAF testing only. If that's correct, doesn't that mean you register mock services/dependancies in the WAF factory instead of constructing the classes yourself via the constructor?
Hi Nick. Great content. Would you consider this to be production ready? Also waiting for that follow up video on this.
Did you make a follow up video on the api design?
This uses WAF for unit testing tho which you you mentioned you don't recommend from your previous video.
thank you Nick ... I like it ... :)
Any advice or suggestions on how to share the Request/Response classes for the features with some sort of front end project like blazor without recreating classes or duplicating code. Trying to come up with a good architecture and combine projects in one solution with the blazor project, a shared class library project and the fastendpoints minimal API project. The shared class library project would hold DTO classes. Would love to hear how others are structuring when using fastendpoints minimal api. Thanks all.
1. What is the difference between the Ardalis implementation and the FastEndpoints implementation? They seem rather similar, adressing basically the same problem. Is it simply an implementation preference?
2. In your latest clean minimal api github repo you are not using the FastEndpoints mapper. Again, is it a personal preference to not overcomplicate things?
Awesome content Nick, much appreciated!
1. The Ardalis one is based on controllers. FastEndpoints are based on minimal APIs, which makes them more efficient. Conceptually are the same idea but the FastEndpoints approach is based on the new tech.
2. I am using FastEndpoints in that repo
Very very cool 👌🏻
Hey, great video. Combined with the one from NDC Oslo this is so good. A bit off topic, but in your videos, your keyboard is very silent, so interested to know which keyboard you're using :). Keep up the good work
I’m using a Logitech MX Keys, specifically because it is so silent but still fairly satisfying to use
@@nickchapsas Ahh yes oh course, Keyboards are a hard thing to choose :)
very good vid.
Hello Bro. Which's font you used in Rider that shows here your video?
yes I agree.
itching to try them them out on VS 2022 but the download takes forever
Hi Nick, your videos are super. Just want to check in your website - if we buy essentials package, minimal apis are not included - will you give that as present or we need to buy that separately? Thanks and keep up excellent work.
Hey Mehdi. Bundles are logical groupings and I don't consider the Minimal API course part of that bundle. When more API related courses are added they will be in a separate bundle but there is no plan to add it in any bundle right now. it has to be purchased separately.
I still prefer your way of structuring. However will look into this!
Honetstly, don't understand why it is better than controllers. If I have some CRUD, I can have 1 controller, explicitly inject services without property magic, specify routes and stuff with attributes in elegant way. Here I need to have a class with two methods for 1 endpoint. What problem does it actually solve?
Controllers by definition violate SOLID. Both single responsibility and open closed are fundamentally violated. With this approach you simply have a 1:1 relationship to a single endpoint. Not injected services that aren’t needed, no performance impact with action filters or middleware that isn’t needed. Need a new endpoint? Create new handler. Don’t need it anymore? Delete the endpoint. Need to change something? You only change that single class. It is by definition better but the problem is that .NET devs are so used to MVC that can’t see anything else as a viable option
Search for a youtube video called "The .NET Docs Show - Controllers are Dinosaurs: The Case for API Endpoints"
@@nickchapsas Interesting opinion
Issue for me is swagger support of minimal API. Currently there is no XML documentation supported so you can't document your endpoints.
I believe they added it in a recent version.
@@duznt-xizt do you have any link for that? Would be great if they have added it.
@@PelFox YT doesn't let me post links. Go to the doc site and click on the left menu where it says "Swagger Support". It's the 4th headline from the top. There's a method called Summary() for describing the endpoint and you can write XML comments on DTOs.
To my untrained eye this library looks like the same features of minimal API in NET 6 just structured differently. Perhaps I just haven't worked with minimal API enough, but I think it has all the same capabilities in a syntax that is equivalent in complexity and extensibility. I don't see the added value. Would have been nice if the video did a bit of compare and contrast so I could understand what's better over the standard functionality.
Structure is everything. Using node’s express library, you can structure your api in hundreds of different ways. That doesn’t mean that everyone using node can build a well structured api with express. This is what this library does best. It sets you up in a well designed structured way with tools that you will almost certainly use. To phrase it a bit different, everyone has seen the Mona Lisa and everyone everyone can get paint, brushes and a canvas, but not everyone can use them to paint the Mona Lisa. It’s the same thing with programming
Can you do a video comparing MediatR to FastEndpoints?
I want to launch my api as by default index.html in vs code I have used launch url but won't worked for mw
Hymm... I don't program any web at all so all this stuff seem exotic too me. It also don't look minimalistic to me. For example I'm struggling to figure out the benefit of this base "Mapper" class. Since all this is static already you could just simply create something like this:
public static class Map {
public static WheaterForecastRequest FromEntity(WeatherForecast e)
=> new WheaterForecastRequest {
...
}
}
and still end up with the same
Forecasts = forecast.Select(Map.FromeEntity);
So what is the purpose of all this extra work?
The only benefit I see is that you can jump to the 'FromEntity' function straight from the Endpoint's signature but I don't think such thing is a good trade, considering all the obfuscating boilerplate...
Hey there. I am taking your minimal API course on teachable and it's great so far, but I am trying to figure out how to reduce request validation boilerplate code in my endpoint handlers. You mention in it, as well as I believe another video of yours on minimal API that you can extract it out into middleware, but I am having a hard time figuring out how? I always used filters in MVC but now since it is not possible in minimal API, I would like to learn how to roll my own pipeline. Can you do a video explaining? thanks for the great content.
Hey there. So currently, there is no "Generic" way to do it on the API level. You really have 2 options. Either plug in MediatR and use a Pipeline filter which I show here: ua-cam.com/video/2JzQuIvxIqk/v-deo.html or if performance doesn't matter to you you can "cheat" your way into validation with this example: github.com/Elfocrash/DotnetDocsShow.MinimalApis/tree/main/DotnetDocsShow.Extensions.Validation
The .NET team will add filter in .NET 7 so there will be a way better way to deal with validation and the course will be updated. I didn't wanna add a solution in that isn't as performant and will be obsolete 8 months after the course
@@nickchapsas Thank you. yes I was hoping to avoid mediatr if possible because I have already implemented your very useful assembly scanning technique for endpoint registration, but the validation logic just adds so much bloat to my otherwise nice and thin endpoints that I may install it just for the validation.
doesn't seem to show up in the endpoints explorer :/
So do you need to have one class for every single endpoint? Or can you group all weather (POST/GET/DELETE etc) together in one class?
One class per endpoint to implement single responsibility properly
@@nickchapsas you can create one controller per action, what is the difference?
Is this approach alternative to Mediatr?
I feel this is over engineering, but it's really clean.
Can we replace "CQRS" using MediatR with FastEndPoints ? what is your thought ?
Sure you can. You just have to add pre and post processors to deal with api level mapping if you don’t want to have it in the handler itself
Hey Nick! How is it going?
I really really liked this video and I tried to implement something myself using fastendponts, but I found that this tool is really great to build very simple APIs... When you need an API that does the CRUD, for example, the best would you use the Microsoft Default tools.
Maybe in the future, when FastEndpoints get more mature, it would be a good substitute to the Microsoft's default...
What do you think?
FastEndpoints are very good for simple and complicated APIs. I build high performance microservices that aren’t that simple and I didn’t have any problem with FastEndpoints. Here is a REST API for example: github.com/Elfocrash/clean-minimal-api
@@nickchapsas Thank you so much!!
I appreciate your answer and help :)
For sure I'll be looking into the code you mentioned 🚀🚀🚀
is there a way to apply Clean archticture with minimal API?
Yeap, all the same rules apply, it's just that your entry point is no longer the controller but rather the endpoint handlers
This one is better than ApiEndpoints package?
The doc says they support constructor injection too.
After this video they do
Isn’t controllers better since it’s more organized than putting all the minimal api in the main program?
I reviewed this project after watching your video. It looked quite reasonable, implicit property injection and all. For me the deal breaker is the fact that is locks the application logic into the protocol. How would I use this outside of an HTTP request? This feels like Mediatr trapped inside the protocol. I'll stick with Mediatr. Thanks for the video.
I would argue that you don't need MediatR at all and you've been indoctrinated into believing that you do
ctor injection has been added. also even though the main use-case is rest api building, you can make an endpoint class just take in a request dto, do some handling and return a response dto. check the unit testing page on the doc site. there's a "public override Task ExecuteAsync(RequestDto req, CancellationToken ct)" you can use. but gotta take a bit of extra care not to touch any http related convenience methods/properties supplied by the base class and inject via the constructor everything needed to handle the request.
@@nickchapsas we have this thing at work if someone mentions mediatr or automapper that person has to buy lunch for the whole team for a full week lol :p
@@nickchapsas beside mediatr subject, having the logic in the protocol doesn't sounds right if you want to expose the same servive by different means (web api, grpc) or use it straight into a dekstop app.
Having the logic in the business/application layer (thinking about Clean Application) allows you to reuse everything and just consume the Command/Queries into the UI of choice:
In this regard, I don't think that having a mediator (note I'm not talking about the mediatr library) is a bad choice, it allows you to decouple things.
This library maybe could be used to have a declarative endpoint that uses minimal API and do its own mapping stuff but internally it could still make use of a mediator code to handle validation, transactional behaviors, loggings and so on on specific command/queries.
I like it, but is no one going to mention support for Data validation attributes?
I don’t like my model to know how it’s supposed to be validated. That logic should be in a validator
Nick, can this approach replace mediatR + its pipeline behaviors and pre/post processors?
Sure it can. It has all the building blocks there.
Except, in mediatR you could call a handler in another one, with this approach, you could'nt.
@@ahmadal-freihat4864 which you shouldnt.
@@PelFox Agreed 100%. That's how you end up with a big ball of mud.
@@ahmadal-freihat4864 Which is good. As I understood we call only services from handlers in CQRS (and then services can call sub services)
Property injection is an anti pattern because how am I supposed to know it's a dependency when newing up the object. Constructor injection is the only way
But PI supports late binding.
Or at least only inject properties that have an explicit Inject attribute.
@@nickchapsas still it's property injection. I don't think I'll be using this because of property injection anti pattern. I love this idea though. They just need to fix that
@@ryanelfman3520 it's added in the latest version; you can do proper constructor injection now
@@Zashxq oh nice I will need to take a look
How to use RoutePrefix=string.Empty;
In swagger i unable to launched by default index.html page in azure as well as in vs code can someone pls help me for the same
Yes so, being old, all I see is more files than lines of necessary code. Do we really need all this to return 4 values?
9:35 looks like now we can use the constructor to inject.
I tried this ( and worked:
sealed class ProtectedEndpoint : EndpointWithoutRequest
{
private readonly IPermissionFilterFactory _filterFactory;
private readonly ILogger _logger;
public ProtectedEndpoint(IPermissionFilterFactory filterFactory, ILogger logger)
{
_filterFactory = filterFactory;
_logger = logger;
}
// .. continue
}
Hey Nick pls help me i try use the library for production use
hi the coupon code doesn't work, could you give us a new one? thanks!
The idea of the library is great. I truly think that the .NET community will go in that direction regarding Minimal APIs Endpoint/Controller structures.
Seems strange that dependency injection is done by initiating a field instead of having this dependency being injected from the constructor. This opens the posibiliy to have a instance of the endpoint class with it's dependencies being null, that's not good and shouldn't be allowed IMO.
He added DI via constructor in the latest version :-)
Hey Nick love your channel and your content, but could you do if its possible ofc pricing for different reasons, I'm I'm Brazil so GBP is very expansier than BRL haha in anyway keep coding
I'm not a fan of all the implied behaviours. For example, it took me a bit to understand how the route parameter was being added into the request. I assume it was mapping it to the same named attribute in the request but then within swagger you could see that concept trip up when the route parameter and the request parameter was shown. It is unclear what happens if you supply a body with the same shape, does it get overwritten? This is one thing I like from the controller approach is the attributes specifying parameters of the method with [FromBody] and [FromRoute]. It just makes it so much clearer and explicit.
I don't see so much added value here. My expectation is: I create a relational model with a couple of entities and relations, constraints, etc. Then I get a tool that takes all this and creates a structured API for me with all the good stuff: authentication, access control, roles, CRUD, read with a query support similar to OData / GraphQL, DB contraints reflected in C# code, validation handlers I can implement for the very special stuff, etc. All that pluming code is really boring. We used to have this in the past from MS. It was called LightSwitch. It even supported generating structured default UI implementations. If you need to fiddle around with 5 classes plus 3 interfaces for each entity to implement it, something is wrong. It is repetitive work. The effort you have to spend, to do all this manually is hardly ever worth it. You need a BIG business case to pay a SW developer to spend 3-5 days to implement CRUD for one entity.
So my application layer turns into presentation layer? I don't like it somehow... or maybe I'm too old for this.
You should look up Vertical Slice Architecture and why it's actually superior to N-layering. I too had a hard time initially with the concept of putting domain logic in the handlers. What I've found is that there's really no need for an extra layer of abstraction unless you need the business logic to be portable and it needs to be referenced from multiple different projects. Also ultimately there is no presentation layer when building Web APIs. There is always only a Request > Handling Logic > a Response.
Would an API with about 100 endpoints be smart to do using this approach?
Sure, why not. It really depends on how those endpoints are organised. Are you doing vertical slices and splitting by feature? No problem at all. At that size I would simply split this service to smaller ones but it’s totally doable
as always 👏🏽👏🏽👏🏽
What I don’t really like is that you put routes very far from the request classes. That leads to errors that cannot be simply eyed out or warned about with compiler/ide.
I have been watching this project for a long time. The idea is good, but the implementation in some places is not perfect, in my opinion. For example, dependency injection at the endpoint is not implemented in the best way. It was also strange for me to see the contents of method "Configured" not in a fluid style.
Although the project is developing and improving swiftly, so I believe that many changes are still ahead.
I agree with you 100%. I actually have a video coming in a week, talking people through why I think the design of the library isn’t great. I think it does a lot of things right but it deviates quite a bit from the general .NET “familiarity” that such projects should have
Hi Nick, the Minimal15 coupon is not working for me, the page says that is invalid, please could you check it?
I'm a brazilian developer and the discount will help me a lot.
The coupon was for the first 100 users, and they are all used
@@nickchapsas There is any chance you offer a new coupon? Please🙏
Tried Minimal API, but calling vendor only supported XML and that’s not available in Minimal. At least, I couldn’t figure it out. That’s pretty opinionated.
So... should one just use this library and even bother with a chapsas minimal API course?
This library is just one opinionated implementation. If you don’t want to know the inner workings or how you can create something that fits your own needs, then you probably don’t need to no. If you are planning to get the most out of minimal APIs though then you might want to take it.
@@nickchapsas understood. 👍
So instead of using Controllers, let's scale back and create structureless request handlers in the form of Minimal APIs so that we can add structure back with lots more boilerplate. Win I guess? I genuinely don't get the appeal of Minimal APIs and this kind of library further compounds my confusion.
Controllers come with a lot of useless middleware that is a remnant of MVC. I find controllers a really odd structure and I never liked them. Minimal APIs allow me to fully control the request pipeline and structure as I want it exactly. That’s the appeal. I guess if you don’t wanna think about it too much and just build something, then controllers are fine. If you wanna be more flexible with your solution, then minimal APIs are great
Why should you prefer property injection over constructor injection? I disagree on this.
You shouldn’t. You should prefer ctor injection
👍🏽
The new cool way to build a .NET API is to not build a .NET API
Lol it’s Microsoft land! Another day, another way! So many ways 4 u!!! Lol
I don’t like that the API can return something that is not in a single part of code where the API is defined. This would be a mess with applications with hundreds of APIs
And would be bad from a code review perspective. Code should be optimized for the reader/code reviewer not the writer and this pattern adds confusion to the reader
It is one of my problems with the design. Stay tuned for Thursdays video where I talk about that in detail. I think it’s very fixable and the creator has proven to take feedback very well, with constructor dependency injection already implemented
@@nickchapsas Did this video come out? I've discovered your channel recently and I've been literally devouring the content (This is the type of content I believe I really missed on my way from regular to senior dev). I got very interested in the subject and would love to hear more critique/see the video where you try to fix the issues you see here.
@@KonradSiuda It did not. I instead sent it to the creator in private and they addressed all my concerns
It's a shame they focus so much on minimal API IMO. It's not feature complete. Everything needs hacks to work. And who asked for it? The normal API is much better and easy to setup
Is it though? Or are you just used to it? Because I’ve thought the same thing until I asked people without api experience and all of them found minimal APIs easier to use. The 2 features that they didn’t have were form files and filters. We are getting both in .NET 7. I don’t see a world where I build a new api with anything but minimal APIs. I would be leaving a lot of performance on the table too.
@@nickchapsas I like when things are declared and explicit. I don't like too much magic going on behind the scenes. I don't like it's more difficult to tweak, just to make the template as small as possible. No versioning support yet.
I also don't like the new Program.cs file that leaves out namespace, class name, etc. Where are the args[] parameter coming from? Magic.
I feel this is a trend. And it goes against what makes C# nice. Explicit and strict language, that does what it says.
I dont quite like the fact that http verbs are slipping through to my handler logic (e.g. business logic). something that combines source generator with Mediator request/response would be the ultimate goal.
@@mw3653please do enlightened me.
I was excited for this video but am very disappointed in the amount of ceremony required to do something so simple. Why not use attributes for request methods? Why not use method name for endpoint route? Why not use method parameter types for mapping data? Seems like belt and suspenders to me.. very typical of C# and the main reason why so many developers have moved to other ecosystems.
The only thing I disagree with is the method name. It is very very dangerous to leave it up to the method name to determine the route. It could definitely be better which is why I made the video. So more people can see it, then the author can see the reaction and try to address it. Or simply someone else forks it and they make their own
The rules should be done using actually csharp and not functions.
Not a big fan of the word "Send" here
Yeah I wish they simply used the generic T type to return it instead of using Send. You can have double send or no send at all and the code will still compile.
No constructor injection is a non-starter. What the hell is wrong with the world.
It was fixed alongside a lot of other feedback. It's way better now
I hate the term “API”. It’s way too vague and overused. Wish we could come up with terms that were more specific to what we were taking about. Hell Web API or REST API would even be better than just API alone, yet there are entire companies named around this acronym.
Hate this library, lots of boilterplate code.
Overengenering
I downloaded you Github repository for this but it seems that lots have changed in FastEndpoints. I had to update the packages but I still got the error that there is no "ErrorResponseBuilder" app.UseFastEndpoints(x =>
{
x.ErrorResponseBuilder = (failures, _) =>
{
return new ValidationFailureResponse
{
Errors = failures.Select(y => y.ErrorMessage).ToList()
};
};
});
First time I see Nick laughing 😆Epic! ua-cam.com/video/z32_7KgCr6c/v-deo.html
You should check the co-pilot video then :D