Write cleaner APIs in .NET 7 with MediatR

  Рет қаралды 59,280

Nick Chapsas

Жыл бұрын

Get started with Octopus Deploy: oc.to/nickchapsas
Check out my courses: dometrain.com
Become a Patreon and get source code access: www.patreon.com/nickchapsas
Hello everybody I'm Nick and in this video I will show you how you can very easily integrate .NET's Minimal APIs with MediatR using the brand new .NET 7 AsParameters attribute in a very elegant and testable way.
This video is sponsored by Octopus Deploy
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasGitHub
Follow me on Twitter: bit.ly/ChapsasTwitter
Connect on LinkedIn: bit.ly/ChapsasLinkedIn
Keep coding merch: keepcoding.shop
#csharp #dotnet #dotnet7

Пікірлер: 243
@nickchapsas
@nickchapsas Жыл бұрын
I want to formally apologise to everyone for using age=60 in the video. 0 and 9 and next to each other and I missclicked the button and only noticed during editing. I can do better.
@weluvmusicz
@weluvmusicz Жыл бұрын
wait what? :D
@barloc2
@barloc2 Жыл бұрын
Apologies accepted. We are all human beings, mistakes can happen.
@pdevito
@pdevito Жыл бұрын
Ruined
@redouane5626
@redouane5626 Жыл бұрын
you should apalogize for naming it MinimalatR 😑
@dungimon1912
@dungimon1912 Жыл бұрын
huh?
@qwer1234cvb
@qwer1234cvb Жыл бұрын
Instead of separating requests and handlers in different folders (or even different files), I find it way more convenient to put both query and handler into the same static class. E.g. ``` public static class GetUsers { public record Query(int Age) : IRequest; public class Handler : IRequestHandler { ... } } ``` It becomes very handy when you need to go to definition by F12, or when writing tests and can add the static to usings and then operate with just Query and Handler, without those long names.
@buriedstpatrick2294
@buriedstpatrick2294 Жыл бұрын
To make your code even neater, remember you can use records instead of classes for your MediatR requests.
@Suriprofz
@Suriprofz Жыл бұрын
And make them immutable.
@aj.arunkumar
@aj.arunkumar 3 ай бұрын
i have a question regarding records.. are domain entities supposed to be defined using records ? if so, we cant use EF with records, so what are we supposed to do..? create separate classes for EF and do mapping ?
@SamueleFurnari
@SamueleFurnari Жыл бұрын
I love, suggest and use this approach in all my projects, exept the demo projects. i call this a little design overhead that gift us the testability, SOLID patterns application and so better code. great video Nick! 💪
@CarmenSantiNova
@CarmenSantiNova Жыл бұрын
Great video as always! We have been using this exact scheme for a while now (1-1.5 years) in production and it works as a charm. We only have one webapi endpoint in our system that handles all requests (not entirely true but ask if you want to know more about it). Everything is POST:ed to the server, so we do not use the verbs. And the posted object from the client is normalized as such (serialized via JSON) and defined in TypeScript: class Message { string Type; object Data; // JSON Serialized data } This means that we do not have to map endpoints on the backend. We only register handlers to the mediator, i.e. MediatR (which we've replaced with MassTransit). On the client side all the types supported are mapped just like you would map endpoints on the backend. The reason is that different types might be handled by different endpoints (domains basically). I would argue that protocol specifics (such as web urls and parameter formats) are not a concern that the user of the request client should handle. // Usage on the client side. _ourRequestClient.Send(new CreateUserRequest() { Name = "A", Age = 10 }); What you have reached in your code is a protocol agnostic solution where the handlers doesn't know anything about i.e. webapi. By doing so, you can now easily replace the webapi with i.e. gRPC or even an eventbus solution. So be very careful not to introduce webapi (or any protocol specific stuff) in your handler. So the IResult should definitely be replaced with an abstraction that can be mapped into IResult since that is WebApi specific.
@barloc2
@barloc2 Жыл бұрын
The first example for the age mapping was 60 instead of 69. I hope everything is OK with you Nick, you don't seem to be yourself nowadays.
@nickchapsas
@nickchapsas Жыл бұрын
I MISS CLICKED THE BUTTON DON'T JUDGE ME
@StigBrembo
@StigBrembo Жыл бұрын
Love this! I changed your extension method a bit, so I could make use of the OutputCache in .Net7 too.
@andrewalexopoulos921
@andrewalexopoulos921 Жыл бұрын
Great video as always! Nice usage of mediatr lib as well :)
@benjamincharlton3774
@benjamincharlton3774 Жыл бұрын
Brilliant, interesting, engaging as always. Thank you, Nick! If you'll accept some respectful, constructive criticism, it is that your latest videos are presented too quickly. Anybody genuinely interested in what you're doing has to pause and rewind and pause again multiple times. You're clicking and typing at the same speed as you would be if you were working, not teaching. I hope the feedback is helpful.
@pilotboba
@pilotboba Жыл бұрын
Or use the speed controls on the viewer. I watch 99% of my content at either 1.5x or 1.75x depending on the presenter. But there are options to slow the vid too.
@bernardo44250
@bernardo44250 Жыл бұрын
I didn't know this video existed! Thanks bro! Really grateful.
@scottatkinson7083
@scottatkinson7083 Жыл бұрын
Hey Nick, really enjoying the content so far. Just wondered what courses you're planning on bringing out soon?
@FraserMcLean81
@FraserMcLean81 Жыл бұрын
Awesome feature and video, thanks Nick! I am interested to know more about how you would automatically register endpoints using the HttpGet and other attributes.
@Velociapcior
@Velociapcior Жыл бұрын
This is in my opinion single handedely the best way to create Minimal Api, can't wait to show this to my colleauges. You are MVP Nick. Microsoft MVP
@DrCox-xx8tu
@DrCox-xx8tu Жыл бұрын
I prefer FastEndpoints to build APIs. You might want to give it a look as well.
@antonmartyniuk
@antonmartyniuk Жыл бұрын
It looks nice, a Mediator way to structure the minimal APIs. Minimal APIs + MediatR = ❤️
@nocgod
@nocgod Жыл бұрын
Very interesting, looks like without controllers we are seeking the same structure. Would be interesting to investigate the performance diff (mem, CPU, through put) between minimalApi, minimatorApi, webApi (controllers)
@framidox3757
@framidox3757 Жыл бұрын
You are a life saver! Kudos to you! You rock!!
@digitalhome6575
@digitalhome6575 Жыл бұрын
Love it, learned it, living it, however.. you need a follow-up video on how/where to add swagger documentation attributes on this. I'm currently extending on your example to add some fluentvalidation to this, and once I figure out the swagger docs thing, microservices will by flying left & right :)
@victor_pogor
@victor_pogor Жыл бұрын
Amazing video. I remember in one live session when you discussed the minimal APIs, I mentioned that this could be used with MediatR (to keep the endpoints clean and to move the handlers for example in core/application layer), and you said something like "why would you use another handler if you have the minimal API handler (delegate)" ))
@nickchapsas
@nickchapsas Жыл бұрын
Don't think of this as an application layer. This is still the UI/API layer. It is just more testable and strucuted
@victor_pogor
@victor_pogor Жыл бұрын
This is a presentation layer, I meant to move the handlers in an aplication layer (in context of clean architecture) and keep the presentation layer as simple as possible.
@nickchapsas
@nickchapsas Жыл бұрын
@@victor_pogor You can structure your project however you want. In the concext of the video mediatr is used on the presentation layer. If you wanna split that then go for it.
@Mikebutawski
@Mikebutawski Жыл бұрын
This was just awesome! Thanks a lot!
@karthiksrivatsa8243
@karthiksrivatsa8243 Жыл бұрын
We can generate swagger documentation as well and also use fluent validation. Combining all these will definitely make cleaner API.
@pablocom
@pablocom Жыл бұрын
Loving this new .NET 7 feature
@tonongah102
@tonongah102 Жыл бұрын
Thanks bro that was really helpful
@amantinband
@amantinband Жыл бұрын
That's very clever, actually. One of the reasons I split Contracts from MediatR requests is that the request can't always capture all the data sent from the client. This concept, with some tweaking, has the potential to be a fun library 🤙🏼
@nickchapsas
@nickchapsas Жыл бұрын
With this approach you can capture everything. Query string with [FromQuery], body with [FromBody], form with [FromForm], headers with [FromHeader] and route with [FromRoute] so there is nothing you'll be missing here.
@drewkillion2812
@drewkillion2812 Жыл бұрын
@@nickchapsas there is also the HttpContextAccessor as well
@taufikdev88
@taufikdev88 10 ай бұрын
love the way you create an extensions class for registering everything
@TimurMANDALI
@TimurMANDALI Жыл бұрын
Awesome video, thanks Nick! , for .NET6 users : public record ExampleRequest(int? Age, string? Name) : IHttpRequest { public static ValueTask BindAsync(HttpContext context) => ValueTask.FromResult(new ( Age: int.TryParse(context.Request.Query["age"], out var age) ? age : null, Name: context.Request.RouteValues.TryGetValue("name", out var name) ? (string?) name : null )); }
@wojciechwilimowski985
@wojciechwilimowski985 Жыл бұрын
You made the middle ground between classic and minimal APIs - minimal controllers!
@xian9029
@xian9029 Жыл бұрын
Very helpful..thanks a lot.
@jonholt8429
@jonholt8429 Жыл бұрын
This is appealing, and gets me one step closer to ditching the controller for a minimal api. The other barriers to me are Swagger support (can this be easily added for minimal API?) and company policy on non-LTS versions (saw your video on that and agree, but wheels of change can turn slowly)
@akzual50
@akzual50 Жыл бұрын
You should be able to facilitate that based on the swagger ext method which does it for controllers
Жыл бұрын
Nice video. I was just looking at FastEndpoints and they seem to provide very similar functionality but they are available on version .NET Core 6 which is pretty cool.
@nickchapsas
@nickchapsas Жыл бұрын
FE is my personal prefered and recommended way to build apis in .NET.
@AyahuascaCeremony
@AyahuascaCeremony Жыл бұрын
Another great video. Towards the end you mentioned the idea of not depending on IResult in your Handlers but using a mapper instead. Could you do a short video to explain that and how to implement it? TIA
@nickchapsas
@nickchapsas Жыл бұрын
I will be making a video on that topic indeed
@paulward8087
@paulward8087 Жыл бұрын
Reminds me of a CQRS approach I toyed with some time ago.
@diligencehumility6971
@diligencehumility6971 Жыл бұрын
Great video and great usage of MediatR. But you do end up with all your application logic living inside the API project. And then we are back to clean architecture
@jamesmussett
@jamesmussett Жыл бұрын
I recommend forwarding the CancellationToken to mediator from the delegate, otherwise it will just use the default CancelationToken in the handler.
@nickchapsas
@nickchapsas Жыл бұрын
Yeah without passing the CT from the handler's patameter's to the Send call, the cancellation won't be triggered
@sergiik2168
@sergiik2168 Жыл бұрын
You may inject some own CancellationTokenProvider service, which would get CancellationToken from HttpRequest.RequestAborted, directly to infrastructure layer (like repositories or custom clients to 3rd party services). In that way you don't need to pass CancellationToken from controllers to (i.e.) repositories through business layer at all.
@PanzerFaustFurious
@PanzerFaustFurious Жыл бұрын
That's why I recommend to set "CA2016: Forward the CancellationToken parameter to methods that take one" to "warning" severity.
@Gobba61
@Gobba61 Жыл бұрын
Could you elaborate on how you do this if you dont mind?
@ADSNGreenLife
@ADSNGreenLife Жыл бұрын
Nick you are dam good man!! bravo
@obiwanjacobi
@obiwanjacobi Жыл бұрын
Nice one!
@bryanlewis3643
@bryanlewis3643 Жыл бұрын
Nick, how would you compare this to FastEndpoints? We have used Mediatr in the past with a traditional Controller full of mediatr calls for each endpoint, and I recently created a proof of concept using FastEndpoints. This seems to be a bit of the merging of the two. What advantages/disadvantages do you see with this new idea over FE?
@nickchapsas
@nickchapsas Жыл бұрын
I prefer FastEndpoints. It is faster, has full support for all the things you will ever need and it gives a better overall experience. This is just if you wanna build something simple with a little bit of strucute. FE is still my favourite and recommended way of building APIs in .NET
@kippie86
@kippie86 Жыл бұрын
I can't really find much documentation about the AsParametersAttribute. From which sources does it map values? Is it possible to pass in values from a custom ValueProvider? In my case many controllers have a [FromClaims] attribute on one or more parameters, and it would be great if those could just automatically be mapped into my IRequests
@nickchapsas
@nickchapsas Жыл бұрын
All [FromXXX] attributes work inside the request
@DevonLehmanJ
@DevonLehmanJ Жыл бұрын
I don't generally like using either minimal apis nor mediatr, but this combo makes it much more appealing
@EternalVids
@EternalVids Жыл бұрын
Out of curiosity, what are your reasons for disliking MediatR?
@DevonLehmanJ
@DevonLehmanJ Жыл бұрын
@@EternalVids I haven't used it much, but from my understanding: if i had a service method e.g. "AddObject", and I wanted to call that from a controller, that's all great. The handler will update the database and do everything it needs to do. But now suppose that I have some other endpoint where i need to add both AddObject and AddChildObject. Now I either: need a new handler to do both, or i need to embed one handler inside another, or I need to create two separate requests to save each object. This would result in two separate database saves, and all the other one-time cruft. In addition, i would find it annoying to have to say "new Request().Handle()" (or however you trigger mediator), rather than just calling _myInjectedService.Method(). This gives me a lot more flexibility to re-use code within your injected services, and also makes the code much more navigable as i can do Go To Implementation on a method, but not on a call to mediatr.
@EternalVids
@EternalVids Жыл бұрын
@@DevonLehmanJ I guess it's a tradeoff. Using MediatR saves you from having to inject those individual services into your WebApi controller classes. MetiatR takes care of the injection for you, so all you need to do is just call the _mediator.Send(request), without worrying who (or multiple whos) handles the details. Also typically you don't need to create a Request object yourself, depending on how your queries are structured. I personally just use Endpoint([FromQuery] request), and pass the resulting object directly to MediatR. You end up almost no code in your controller classes this way, it all fits into single line expression body statements for each. public Task Get([FromQuery] Request request) => _mediator.Send(request); Personally my only pain-point is the fact that it's not easy to navigate from the WebApi mediatr invocation to the actual handler. I've seen people placing Handlers in the same files as Request definitions as a workaround, but I am not convinced that's the best way.
@kabal911
@kabal911 Жыл бұрын
@@EternalVids I think it definitely is the best way, combining them. The same as in a traditional controller. The “HttpGet” attribute and the controller method signature is kind of the request, while the method/body is the handler. We even store our FluentValidation implementations for our requests with the request and the handler. They are all connected. As a trade off, you could store them in different files in the same folder, aka structure by feature. Structure by type for me is just not a good architecture, when it comes to application business logic. I still do however keep the controllers in a controller folder, mostly because I haven’t thought too much about that side. But it doesn’t really matter, just what you and your team is comfortable with and is most productive with.
@krccmsitp2884
@krccmsitp2884 Жыл бұрын
Veeery nice! 👍
@rade6063
@rade6063 Жыл бұрын
Now that you can use mediator, fast endpoints, and others like you showed here and on course which will you use as your go to solution/template?
@nickchapsas
@nickchapsas Жыл бұрын
Fast endpoints is still my go to. It is faster and has way more functionality and better structure. This is more of just a simple alternative if you wanna hack something together and still have some structure
@daxyhrgaming5292
@daxyhrgaming5292 Жыл бұрын
I really liked this approach, but when fiddling around with this, I seem to run into issues when I combine this with the ValueOf package that you demonstrated a while ago. I already added the TryParse function to my objects, but I’m still getting weird behavior (like objects are being expected instead of strings).
@nickchapsas
@nickchapsas Жыл бұрын
You wouldn’t combine this with ValueOf
@jonathanperis3600
@jonathanperis3600 Жыл бұрын
Can we have IResult out of AspNetCore project to build this inside a shared library?
@cmartinez4727
@cmartinez4727 Жыл бұрын
Is mapget() better than doing it old school via apicontroller? Or is mapget more for small project while apicontroller classes is better for big projects?
@RuslanSafroniuk
@RuslanSafroniuk Жыл бұрын
Hello! How about put request with first parameter from route and second parameter from body?
@kasperkadzielawa8658
@kasperkadzielawa8658 Жыл бұрын
Just a few more steps and you reinvent the classic controller class approach xP
@maacpiash
@maacpiash Жыл бұрын
I have been keeping the handler methods of my minimal APIs inside static classes as static methods, as described in 2:00. Is there going to be a problem in terms of scopes?
@nickchapsas
@nickchapsas Жыл бұрын
No there isn't, as long as you injecting everything through the handler's parameters
@VinayKumar-ki5fd
@VinayKumar-ki5fd Жыл бұрын
Very gooood :)
@JonathanPeel
@JonathanPeel Жыл бұрын
Is there a way to program minimal API on an interface, and then easily create a client, based on the interface?
@idzyubin720
@idzyubin720 Жыл бұрын
Great job! So, maybe let’s consider pros & cons of mediatR? As I know, it has some problems with performance and memory Maybe, is there alternative tool?
@kippie86
@kippie86 Жыл бұрын
Nick already talked about the performance of MediatR in this video: kzbin.info/www/bejne/mJLMeWaclLl5nLs
@idzyubin720
@idzyubin720 Жыл бұрын
@@kippie86 thanks, I’ve seen this video yet
@endmrx
@endmrx Жыл бұрын
Thanks for the news! Minor: await Task.Delay(...); → await Task.CompletedTask; ?
@miindgame
@miindgame Жыл бұрын
Let's say I have a Clean Architecture type project, but would like the minimal API approach instead of all the separate Controller.cs files. And let's say, my old controllers handle a result monad to give the appropriate responses (200,404,500, whatever). Would it even be possible to then use only one mediatR handler on the presentation layer?
@nickchapsas
@nickchapsas Жыл бұрын
One handelr per request not one handler for all requests
@miindgame
@miindgame Жыл бұрын
@@nickchapsas Ah of course, MediatR in the presentation layer should then just mediate the separate files I used to have. And those will still follow the rules they used to do when they were in separate files. Thank you! :)
@michaelfernandes6893
@michaelfernandes6893 Жыл бұрын
Is this not an example to couple youre frontend end to youre backend as a bad practice?
@GleichCraft
@GleichCraft Жыл бұрын
Cool Stuff! Thanks your for your great content. I think this is a great approach, but I do not agree with putting the IResult in the handler. By returning IResult in the handler, you force the consumer of the IRequest (mediator) to use HTTP. If you later on decide to build a CLI out of your api, use SignalR instead of http or something else you cannot without dealing with an HTTP Object (IResult). So I perfer either returning the mapped DTO (Response) or returning the domain object which then needs to be mapped by the API controller/ minimal api lamda (what ever you want to call that :D), but this depends on wether you need this extra mapping layer in your application (most dont, so we should be practical). I think the benefit of returning IResult is so small compared to the crazy http contract you are forcing. What do you think?
@nickchapsas
@nickchapsas Жыл бұрын
There is no application later in this example so where the IResult lives doesn’t matter. Stop thinking like clean architecture is the only way to build software. It’s not
@thespicycoder5583
@thespicycoder5583 Жыл бұрын
Nick, can you please do a mini series on Dapr
@isnakolah
@isnakolah Жыл бұрын
Hey Nick, great video. How though do you get your rider working with .NET 7?
@nickchapsas
@nickchapsas Жыл бұрын
Never had a problem wth it not running. I'm not even on the EAP
@isnakolah
@isnakolah Жыл бұрын
@@nickchapsas I found my issue, I kept on installing the x86 version instead of x64. I now know better
@volodymyrliashenko1024
@volodymyrliashenko1024 Жыл бұрын
Hello Nick, do you know any big open source project where MediatR is used? I would like to see how it looks. Thanks!
@Lammot
@Lammot Жыл бұрын
There's always eShopOnContainers.
@suleymanov1990
@suleymanov1990 Жыл бұрын
Also CleanArchitecture template and NorthwindWindTraders from Jason Tyler.
@marcomannarino7930
@marcomannarino7930 Жыл бұрын
Nice:)
@MrAKAQUAN
@MrAKAQUAN Жыл бұрын
Thank Nick, the video is greate, but to be honest, I don't see much the benefit of using minimal API + Media vs traditional API controller + service layer. Could you help to explain? Thanks
@nickchapsas
@nickchapsas Жыл бұрын
Minimal APIs have a stripped down request flow. There is no such thing as validation middleware for example by default. You control the full flow and you opt into the feature you want so if I want validation I simply create a validator pipeline on top of this and I also validate my incoming items in a very clean way. The controller approach for validation is way clunkier and heavier. This is just a single example.
@andreasandersson7685
@andreasandersson7685 Жыл бұрын
Hey Nick. It appears the properties inside a post requests becomes null. Are there any fix for this? :) Thanks for the video. //Edit: I removed [AsParameters] from MediatePost(), that solved the issue.
@VijayKumar-wy9ku
@VijayKumar-wy9ku 7 ай бұрын
Isn't it increasing the boiler plate? You are gonna have n handlers(classses) for n endpoints.
@danielegiovanetti9258
@danielegiovanetti9258 Жыл бұрын
Very special content from you. Thanks so much Nick. Does mediatR decrease response time performance?
@nickchapsas
@nickchapsas Жыл бұрын
Technically yes but realistically if your endpoint is doing any sort of work, form compute to network/db calls, it is extremely insignificant comparatively
@danielegiovanetti9258
@danielegiovanetti9258 Жыл бұрын
@@nickchapsas thank you
@samsonquaye9913
@samsonquaye9913 Жыл бұрын
How do we handle post?
@Arkensor
@Arkensor Жыл бұрын
What is your opinion on this kind of "seperation of configuration" with that you often need to put something explictly into the program.cs to register it. Why not for example decorate all Handlers in your example with an attribute like [HandlerRoute("example/{name}")] and find all handlers by base class via reflection and take their attribute data to register. I often use annotations like this so that if I add a new handler I only add that one file that knows everything about itself and let the program.cs just auto detect everything. I dislike adding the actual thing and then in program.cs I need to explictly tell the system that I added it. A lot of program.cs (or if older Startup.cs) files I see are filled with like 100 service registrations etc.
@akzual50
@akzual50 Жыл бұрын
Extension methods are what I use for that
@vivekkaushik9508
@vivekkaushik9508 Жыл бұрын
Honestly, I think its still complicated for any beginner or even an average c# sharp dev like myself. Even though it works perfectly and looks good but if I copy-pasted this boilerplate in my project, my team would ask me to justify it and I'm afraid I wouldn't do a great job doing that. What's wrong with cut-paste the implementation using Abstract classes? I haven't done this. Anyone any idea?
@user-iv7uj7lx8n
@user-iv7uj7lx8n Жыл бұрын
My main problem with MediatR (and the reason why I don't use it) is that it prevents me from easily navigating from the endpoint to the handler within Rider. If I use a service or just another method, I can navigate to it easily by ctrl+clicking the method call. With MediatR I'd need to search for the handler explicitly. Is there any smart way to get around this?
@jobumble8829
@jobumble8829 Жыл бұрын
Put your Request and RequestHandler in the same file.. bingo... Navigate to requests..
@letifere
@letifere Жыл бұрын
I do the same as Jo Bumble, put Handler and request objects in the same file.
@bjarkeistruppedersen8213
@bjarkeistruppedersen8213 Жыл бұрын
Does this work with the new MapGroup they added to v7?
@nickchapsas
@nickchapsas Жыл бұрын
Yeah can't see why that might be a problem
@mana20
@mana20 Жыл бұрын
Is it hard to Unit Test using mediator? I know I ran into some issues with CAP handlers
@nickchapsas
@nickchapsas Жыл бұрын
I never had a problem unit testing it
@akzual50
@akzual50 Жыл бұрын
I used SpecFlow for my BDD implementation. Test first development approach. Essentially what youve asked isn't even a question when you're test first. You build your behavior logic in behavior modules for the test scenarios first. Then you implement them into the service collection and call them with the provider.
@Tof__
@Tof__ Жыл бұрын
I really dont know, so dont hate on me please, but why I would need to use MediatR, when Ardalis.Endpoints are just so much easier to setup and give the same benefits?
@nickchapsas
@nickchapsas Жыл бұрын
No judging here. Ardalis.Endpoints are built on top of Controllers which carry all the middleware and filters of said controllers and that request pipeline. Minimal APIs have a stripped down pipeline so you can use MediatR and add your own pipeline steps with MediaitR extension points, for example validation with fluent validation or logging/metrics. You basically control full flow
@Tof__
@Tof__ Жыл бұрын
@@nickchapsas yeah, so if I understand correctly, that i shouldn't be bothered if I am not using minimal APIs
@nickchapsas
@nickchapsas Жыл бұрын
​@@Tof__ I wouldn't say so. For example, I moved myself from Ardalis.Endpoints to Minimal APIs vs FastEndpoints because I think it's a way better approach. If you want a more performant approach with better feature support then you should be bothered, otherwise, you shouldn't
@steve-ardalis-smith
@steve-ardalis-smith Жыл бұрын
@@nickchapsas I agree if you're moving to minimal APIs (which are the future) you should look at FastEndpoints which implements the same REPR pattern as Ardalis.Endpoints.
@joephillips6634
@joephillips6634 Жыл бұрын
thanks dad
@realsk1992
@realsk1992 Жыл бұрын
Is there an elegant way to do validation with MediatR, without throwing exceptions for the validation errors?
@nickchapsas
@nickchapsas Жыл бұрын
This one is. You simply puth your validation logic in the MediatR pipeline and return the IResult bad request diretly from there
@johnjosephsmith
@johnjosephsmith Жыл бұрын
Where is the source code for this. Unless I’ve missed it I can’t find on GitHub etc
@AngusMcIntyre
@AngusMcIntyre 8 ай бұрын
Why are we moving our endpoint code into multiple places yet _still_ bedding in HTTP concerns to the request handler? There is still place for good old domain mapping here. Or just use controllers. Thats what they are there for.
@ArinSinabian
@ArinSinabian Жыл бұрын
What is better with this approach vs controller classes? For me this seems like you are creating controller classes with minimal api and mediatr.
@nickchapsas
@nickchapsas Жыл бұрын
What’s better is that you don’t violate single responsibility principle. Controllers can have many actions and many services injected in them with some of them not used by all actions. That’s bad. With controllers you also sign up for a bloated request pipeline with that you might not use but they will affect your performance. Here you have a simple and clean 1-1 relationship between endpoint and handler and you can opt into the features you want in a decoupled way with mediatr pielines
@ArinSinabian
@ArinSinabian Жыл бұрын
@@nickchapsas yes totally understand now. Controller classes can become large.
@anthonylerouge9900
@anthonylerouge9900 Жыл бұрын
It is interesting for simple apis but what if you need specific HttpStatus codes? Here you return only 200 but what about 400, 404, ... ? I guess you can kind of normalize the result of the mediator request to kind of be able to handle these types of status codes but still
@nickchapsas
@nickchapsas Жыл бұрын
The Results and TypedResults method contains all the statues you might need. Results.NotFound(), Results.BadRequest() etc
@anthonylerouge9900
@anthonylerouge9900 Жыл бұрын
@@nickchapsas I mean, the extension method is generic, so how do you manage if this request needs to returns 404 and that request 400?
@anthonylerouge9900
@anthonylerouge9900 Жыл бұрын
it works well with the happy path but what about error handling?
@nickchapsas
@nickchapsas Жыл бұрын
@@anthonylerouge9900 Like I said, you just handle the error in the handler and return the appropriate response.
@adrian_franczak
@adrian_franczak Жыл бұрын
What if I want send POST request with body?
@nickchapsas
@nickchapsas Жыл бұрын
Just add the object you wanna map in the request object and use it. The body will be automatically mapped to the object. You can also use the [FromBody] attribute to make it explicit
@goremukin1
@goremukin1 Жыл бұрын
Hi Nick! What is the benefit of using the Mediatr here? Why is this approach better than simple controllers? In case of controllers no need to register each end point in the Program.cs
@nickchapsas
@nickchapsas Жыл бұрын
There are benefits yes, I’ve answered this question in other comments
@jairgza
@jairgza Жыл бұрын
As far as I can see mediatr only knows about ExampleRequest, How mediator knows which handler instantiate and run ?
@Doctor.Livesey
@Doctor.Livesey Жыл бұрын
what if request used several services to make result?
@nickchapsas
@nickchapsas Жыл бұрын
No problem at all. Most services do
@g_weaths
@g_weaths Жыл бұрын
Nick great content as always, but i do find your content sometimes far too fast. If i had one request for you, it would be please slow down a little.
@dropsonic
@dropsonic Жыл бұрын
It seems that you're reinventing the controllers with the help of MediatR :) Or am I getting it wrong?
@paleocomburo
@paleocomburo Жыл бұрын
Had the same thought. Isn't this just an API controller, but via Mediatr?
@nickchapsas
@nickchapsas Жыл бұрын
You are getting it wrong indeed ;) Controllers can have N amount of actions and they are subject to a bloated implicit pipeline. This approach has a 1-1 relationship between endpoints and handling (single responsibility) and has the stripped down version of http handling allowing for a pluggable decoupled implementation of concerns via MediatR pipelines
@lukaszluczko
@lukaszluczko Жыл бұрын
Where can I find repo with this code?
@nickchapsas
@nickchapsas Жыл бұрын
The source code is available to my Patreons
@akzual50
@akzual50 Жыл бұрын
Hey there Nick. I've discovered an approach to not using interfaces for DI. Basically the concrete class which could have its interface drawn from it isn't. Instead you give it mutable properties which a subservice would assign to. The end. This way you can unit test without fabricating mockups in reflection and instead explicitly set the mutable delegates and properties. Ideally your services won't have data type properties because you code for behavior, not data.
@richarddunning7459
@richarddunning7459 Жыл бұрын
That means calling services are required to know what values to instantiate their dependencies with, e.g. if you're requiring your database access layer you will need to pass in fake credentials, rather than mocking out a valid response on a query request
@akzual50
@akzual50 Жыл бұрын
@@richarddunning7459 not quite. The DAL would assign its executions to the Func variables in the adapter class. The adapter class will have high level methods that invoke those function calls. The DAL services will use the adapter class as a dependency to do the assignment and thats it
@QuickZ_
@QuickZ_ Жыл бұрын
uh oh sponsored by OD... What a plot twist.. I expect Microsoft vengeance in the next video. Azure devops cries can be heard through the web
@copycatzen
@copycatzen Жыл бұрын
Isn't AddMediatR registered as scoped by default already?
@nickchapsas
@nickchapsas Жыл бұрын
Pretty sure it’s transient
@adrian_franczak
@adrian_franczak Жыл бұрын
what about fluent validation in this pipeline?
@nickchapsas
@nickchapsas Жыл бұрын
That's where the magic happens because now you can have FluentValidation as a MediatR pipeline on top of the handler which is way cleaner and it can be in just one place
@souleater9189
@souleater9189 Жыл бұрын
This'll be useful
@amrosamy8232
@amrosamy8232 Жыл бұрын
I'd prefer returning a concrete type instead of an abstract interface "IResult" It would be better for swagger documentation
@leonardoformaggi7614
@leonardoformaggi7614 Жыл бұрын
You can use the .Produces() method overloads to generate your swagger appropriately.
@amrosamy8232
@amrosamy8232 Жыл бұрын
I'd say returning Result can be an option as well.
@leonardoformaggi7614
@leonardoformaggi7614 Жыл бұрын
It is. Although with Produces you can specify different responses for different status codes, if you need to. Whatever is best for you scenario.
@IgorChistruga
@IgorChistruga Жыл бұрын
Hey Nick - is the sourcecode somewhere available?
@nickchapsas
@nickchapsas Жыл бұрын
It is. Check the first line in the description
@janvandenbaard5939
@janvandenbaard5939 Жыл бұрын
Will this play nice with swagger?
@nickchapsas
@nickchapsas Жыл бұрын
Sure, just add the Produces extensions methods on the MediateXXX methods and it will be fine
@janvandenbaard5939
@janvandenbaard5939 Жыл бұрын
I was thinking more about visibility of the parameters in swagger. I remember having some issues in NET 6 when binding query parameters to a model that they where no longer visible in swagger. Should have made myself clear. Sorry about that. I wil start setting up a test api in DOT NET 7 and test the stuff you show for myself :) Thanks for all your efforts. It is very much appreciated.
@Gobba61
@Gobba61 Жыл бұрын
@@janvandenbaard5939 did you get the Params showing up in swagger?
@janvandenbaard5939
@janvandenbaard5939 Жыл бұрын
@@Gobba61 I did but it was a cludge which i decided against. I created a model, implemented a BindAsync() method on the model in which i parsed the query parameters into the model. This also means that the query parameters should be declared in addition to the model itself in the endpoint configuration. It all worked but was so a recipe for disaster so we decided to just use the query parameters until .NET 7 is released.
@DarraghJones
@DarraghJones Жыл бұрын
Isn't your weather forecast handler basically a weather forecast controller?
@nickchapsas
@nickchapsas Жыл бұрын
No it is a single controller action
@nofatchicks6
@nofatchicks6 Жыл бұрын
I built the same thing in .net 6. It was a complete pain in the arse. .net 7 will put me out of a job 😅
@AizenSousuke92
@AizenSousuke92 Жыл бұрын
anyone tried this in docker and it works?
@nickchapsas
@nickchapsas Жыл бұрын
Why wouldn't it?
@fatihcihanhizlikan1427
@fatihcihanhizlikan1427 Жыл бұрын
That's Refit. 😀
@weluvmusicz
@weluvmusicz Жыл бұрын
What about Swagger with this approach?
@nickchapsas
@nickchapsas Жыл бұрын
You'd have to add the fluent extensions "Produces" on the MediateXXX calls to describe the endpoint's responses
@fehmianac
@fehmianac Жыл бұрын
Hey Nick, I am wondering about Patch endpoint in Minimal API. Would you give some advice to me ?
@manni.Net60
@manni.Net60 Жыл бұрын
Isnt this becoming closer and closer to Controllers every Time?
@nickchapsas
@nickchapsas Жыл бұрын
You can handle multiple requests in a single controller violating single responsibility. This is a better structure
@PelFox
@PelFox Жыл бұрын
@@nickchapsas You could create one controller per request if you want. You are not forced to put all action methods in the same controller. With VSA you could do one GetAllCustomersController paired with MediatR request/handler.
@nickchapsas
@nickchapsas Жыл бұрын
@@PelFox Yeah at that point why are you using a controller in the first place? Why would you use a grouped routing construct and limit it to one action, and one that comes with a lot of implicitly bloated request pipeline on top of that
@PelFox
@PelFox Жыл бұрын
@@nickchapsas Never said it was good, just said it is possible. Nothing forces you to add multiple action methods in a controller.
@BryonLape
@BryonLape Жыл бұрын
Spring allowed a simpler and cleaner version of this over 20 years ago. Still too much boilerplate code for things that are not necessary.
@nickchapsas
@nickchapsas Жыл бұрын
No it didn't
@roko567
@roko567 Жыл бұрын
I have yet to see a single good reason to go "cleaner" than the MVC patttern
@dmisterb
@dmisterb Жыл бұрын
Hey Nick! Could you make some videos about System.Reactive?
@nickchapsas
@nickchapsas Жыл бұрын
I have one coming in September or October
@pcapcapca
@pcapcapca Жыл бұрын
I'm disappointed with that age of 60
@nickchapsas
@nickchapsas Жыл бұрын
It was a missclick :'(
@yuragutyk8028
@yuragutyk8028 Жыл бұрын
I was looking for this comment)
@hassanmoujahed8956
@hassanmoujahed8956 Жыл бұрын
Why you are
ЧУТЬ НЕ УТОНУЛ #shorts
00:27
Паша Осадчий
Рет қаралды 3,4 МЛН
КАК ДУМАЕТЕ КТО ВЫЙГРАЕТ😂
00:29
МЯТНАЯ ФАНТА
Рет қаралды 8 МЛН
DO YOU HAVE FRIENDS LIKE THIS?
00:17
dednahype
Рет қаралды 113 МЛН
Clown takes blame for missing candy 🍬🤣 #shorts
00:49
Yoeslan
Рет қаралды 18 МЛН
ЧУТЬ НЕ УТОНУЛ #shorts
00:27
Паша Осадчий
Рет қаралды 3,4 МЛН