Write cleaner APIs in .NET 7 with MediatR

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

Nick Chapsas

Nick Chapsas

Күн бұрын

Get started with Octopus Deploy: oc.to/nickchapsas
Check out my courses: dometrain.com
Become a Patreon and get source code access: / 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/ChapsasG...
Follow me on Twitter: bit.ly/ChapsasT...
Connect on LinkedIn: bit.ly/ChapsasL...
Keep coding merch: keepcoding.shop
#csharp #dotnet #dotnet7

Пікірлер: 243
@nickchapsas
@nickchapsas 2 жыл бұрын
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 2 жыл бұрын
wait what? :D
@barloc2
@barloc2 2 жыл бұрын
Apologies accepted. We are all human beings, mistakes can happen.
@pdevito
@pdevito 2 жыл бұрын
Ruined
@redouane5626
@redouane5626 2 жыл бұрын
you should apalogize for naming it MinimalatR 😑
@dungimon1912
@dungimon1912 2 жыл бұрын
huh?
@qwer1234cvb
@qwer1234cvb 2 жыл бұрын
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 2 жыл бұрын
To make your code even neater, remember you can use records instead of classes for your MediatR requests.
@Suriprofz
@Suriprofz 2 жыл бұрын
And make them immutable.
@aj.arunkumar
@aj.arunkumar 6 ай бұрын
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 ?
@benjamincharlton3774
@benjamincharlton3774 2 жыл бұрын
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 2 жыл бұрын
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.
@barloc2
@barloc2 2 жыл бұрын
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 2 жыл бұрын
I MISS CLICKED THE BUTTON DON'T JUDGE ME
@CarmenSantiNova
@CarmenSantiNova 2 жыл бұрын
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.
@digitalhome6575
@digitalhome6575 2 жыл бұрын
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 :)
@nocgod
@nocgod 2 жыл бұрын
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)
@karthiksrivatsa8243
@karthiksrivatsa8243 2 жыл бұрын
We can generate swagger documentation as well and also use fluent validation. Combining all these will definitely make cleaner API.
@SamueleFurnari
@SamueleFurnari 2 жыл бұрын
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! 💪
@amantinband
@amantinband 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@nickchapsas there is also the HttpContextAccessor as well
@FraserMcLean81
@FraserMcLean81 2 жыл бұрын
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.
@TimurMANDALI
@TimurMANDALI 2 жыл бұрын
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 )); }
@taufikdev88
@taufikdev88 Жыл бұрын
love the way you create an extensions class for registering everything
@jamesmussett
@jamesmussett 2 жыл бұрын
I recommend forwarding the CancellationToken to mediator from the delegate, otherwise it will just use the default CancelationToken in the handler.
@nickchapsas
@nickchapsas 2 жыл бұрын
Yeah without passing the CT from the handler's patameter's to the Send call, the cancellation won't be triggered
@sergiik2168
@sergiik2168 2 жыл бұрын
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 2 жыл бұрын
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?
@wojciechwilimowski985
@wojciechwilimowski985 Жыл бұрын
You made the middle ground between classic and minimal APIs - minimal controllers!
@victor_pogor
@victor_pogor 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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.
@StigBrembo
@StigBrembo 2 жыл бұрын
Love this! I changed your extension method a bit, so I could make use of the OutputCache in .Net7 too.
@Velociapcior
@Velociapcior 2 жыл бұрын
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 2 жыл бұрын
I prefer FastEndpoints to build APIs. You might want to give it a look as well.
@bernardo44250
@bernardo44250 2 жыл бұрын
I didn't know this video existed! Thanks bro! Really grateful.
@AyahuascaCeremony
@AyahuascaCeremony 2 жыл бұрын
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 2 жыл бұрын
I will be making a video on that topic indeed
@jonholt8429
@jonholt8429 2 жыл бұрын
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 2 жыл бұрын
You should be able to facilitate that based on the swagger ext method which does it for controllers
@paulward8087
@paulward8087 2 жыл бұрын
Reminds me of a CQRS approach I toyed with some time ago.
@diligencehumility6971
@diligencehumility6971 2 жыл бұрын
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
@antonmartyniuk
@antonmartyniuk 2 жыл бұрын
It looks nice, a Mediator way to structure the minimal APIs. Minimal APIs + MediatR = ❤️
@framidox3757
@framidox3757 2 жыл бұрын
You are a life saver! Kudos to you! You rock!!
@scottatkinson7083
@scottatkinson7083 2 жыл бұрын
Hey Nick, really enjoying the content so far. Just wondered what courses you're planning on bringing out soon?
@andrewalexopoulos921
@andrewalexopoulos921 2 жыл бұрын
Great video as always! Nice usage of mediatr lib as well :)
@pablocom
@pablocom 2 жыл бұрын
Loving this new .NET 7 feature
@gileee
@gileee 2 жыл бұрын
I created something very similar in my learning demo project. Basically all endpoints are individual classes that inherit an IEndpoint interface (which are all auto injected), the interface has a "GetHandler()" method which returns a delegate (which the app.MapGet accept anyway). All my endpoints now look like: public class ExampleEndpoint: IEndpoint { public Delegate GetHandler() => ([FromBody] MyRequest req, [FromQuery] int some, CancelationToken ct....) => ... do endpoint logic } I extended it so that I have an AbstractEndpoint class that inherits IEndpoint and takes HTTP metod type (GET, POST...), the route pattern in the constructor and has a Map() method which can be overridden if your endpoint has some extra info like Produces().... and stuff like that.
@pilotboba
@pilotboba 2 жыл бұрын
Sounds like ardalis' endpoints project (which uses controllers under the hood)
@DevonLehmanJ
@DevonLehmanJ 2 жыл бұрын
I don't generally like using either minimal apis nor mediatr, but this combo makes it much more appealing
@EternalVids
@EternalVids 2 жыл бұрын
Out of curiosity, what are your reasons for disliking MediatR?
@DevonLehmanJ
@DevonLehmanJ 2 жыл бұрын
@@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 2 жыл бұрын
@@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 2 жыл бұрын
@@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.
@GleichCraft
@GleichCraft 2 жыл бұрын
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 2 жыл бұрын
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
2 жыл бұрын
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 2 жыл бұрын
FE is my personal prefered and recommended way to build apis in .NET.
@Mikebutawski
@Mikebutawski 2 жыл бұрын
This was just awesome! Thanks a lot!
@tonongah102
@tonongah102 2 жыл бұрын
Thanks bro that was really helpful
@idzyubin720
@idzyubin720 2 жыл бұрын
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 2 жыл бұрын
Nick already talked about the performance of MediatR in this video: kzbin.info/www/bejne/mJLMeWaclLl5nLs
@idzyubin720
@idzyubin720 2 жыл бұрын
@@kippie86 thanks, I’ve seen this video yet
@kasperkadzielawa8658
@kasperkadzielawa8658 2 жыл бұрын
Just a few more steps and you reinvent the classic controller class approach xP
@endmrx
@endmrx 2 жыл бұрын
Thanks for the news! Minor: await Task.Delay(...); → await Task.CompletedTask; ?
@thespicycoder5583
@thespicycoder5583 2 жыл бұрын
Nick, can you please do a mini series on Dapr
@ADSNGreenLife
@ADSNGreenLife 2 жыл бұрын
Nick you are dam good man!! bravo
@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.
@akzual50
@akzual50 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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
@xian9029
@xian9029 2 жыл бұрын
Very helpful..thanks a lot.
@kippie86
@kippie86 2 жыл бұрын
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 2 жыл бұрын
All [FromXXX] attributes work inside the request
@bryanlewis3643
@bryanlewis3643 2 жыл бұрын
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 2 жыл бұрын
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
@VijayKumar-wy9ku
@VijayKumar-wy9ku 10 ай бұрын
Isn't it increasing the boiler plate? You are gonna have n handlers(classses) for n endpoints.
@QuickZ_
@QuickZ_ 2 жыл бұрын
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
@michaelfernandes6893
@michaelfernandes6893 2 жыл бұрын
Is this not an example to couple youre frontend end to youre backend as a bad practice?
@rade6063
@rade6063 2 жыл бұрын
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 2 жыл бұрын
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
@Tof__
@Tof__ 2 жыл бұрын
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 2 жыл бұрын
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__ 2 жыл бұрын
@@nickchapsas yeah, so if I understand correctly, that i shouldn't be bothered if I am not using minimal APIs
@nickchapsas
@nickchapsas 2 жыл бұрын
​@@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.
@RuslanSafroniuk
@RuslanSafroniuk Жыл бұрын
Hello! How about put request with first parameter from route and second parameter from body?
@dropsonic
@dropsonic 2 жыл бұрын
It seems that you're reinventing the controllers with the help of MediatR :) Or am I getting it wrong?
@paleocomburo
@paleocomburo 2 жыл бұрын
Had the same thought. Isn't this just an API controller, but via Mediatr?
@nickchapsas
@nickchapsas 2 жыл бұрын
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
@cmartinez4727
@cmartinez4727 2 жыл бұрын
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?
@AngusMcIntyre
@AngusMcIntyre 11 ай бұрын
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.
@harbor.boundary.flight
@harbor.boundary.flight 2 жыл бұрын
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 😅
@jonathanperis3600
@jonathanperis3600 2 жыл бұрын
Can we have IResult out of AspNetCore project to build this inside a shared library?
@JonathanPeel
@JonathanPeel 2 жыл бұрын
Is there a way to program minimal API on an interface, and then easily create a client, based on the interface?
@jairgza
@jairgza 2 жыл бұрын
As far as I can see mediatr only knows about ExampleRequest, How mediator knows which handler instantiate and run ?
@isnakolah
@isnakolah 2 жыл бұрын
Hey Nick, great video. How though do you get your rider working with .NET 7?
@nickchapsas
@nickchapsas 2 жыл бұрын
Never had a problem wth it not running. I'm not even on the EAP
@isnakolah
@isnakolah 2 жыл бұрын
@@nickchapsas I found my issue, I kept on installing the x86 version instead of x64. I now know better
@ArinSinabian
@ArinSinabian 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@nickchapsas yes totally understand now. Controller classes can become large.
@sigtermnull
@sigtermnull 2 жыл бұрын
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 2 жыл бұрын
There are benefits yes, I’ve answered this question in other comments
@MrAKAQUAN
@MrAKAQUAN 2 жыл бұрын
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 2 жыл бұрын
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.
@realsk1992
@realsk1992 2 жыл бұрын
Is there an elegant way to do validation with MediatR, without throwing exceptions for the validation errors?
@nickchapsas
@nickchapsas 2 жыл бұрын
This one is. You simply puth your validation logic in the MediatR pipeline and return the IResult bad request diretly from there
@janvandenbaard5939
@janvandenbaard5939 2 жыл бұрын
Will this play nice with swagger?
@nickchapsas
@nickchapsas 2 жыл бұрын
Sure, just add the Produces extensions methods on the MediateXXX methods and it will be fine
@janvandenbaard5939
@janvandenbaard5939 2 жыл бұрын
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.
@johnjosephsmith
@johnjosephsmith Жыл бұрын
Where is the source code for this. Unless I’ve missed it I can’t find on GitHub etc
@obiwanjacobi
@obiwanjacobi 2 жыл бұрын
Nice one!
@vivekkaushik9508
@vivekkaushik9508 2 жыл бұрын
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?
@samsonquaye9913
@samsonquaye9913 Жыл бұрын
How do we handle post?
@danielegiovanetti9258
@danielegiovanetti9258 2 жыл бұрын
Very special content from you. Thanks so much Nick. Does mediatR decrease response time performance?
@nickchapsas
@nickchapsas 2 жыл бұрын
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 2 жыл бұрын
@@nickchapsas thank you
@daxyhrgaming5292
@daxyhrgaming5292 2 жыл бұрын
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 2 жыл бұрын
You wouldn’t combine this with ValueOf
@DarraghJones
@DarraghJones 2 жыл бұрын
Isn't your weather forecast handler basically a weather forecast controller?
@nickchapsas
@nickchapsas 2 жыл бұрын
No it is a single controller action
@krccmsitp2884
@krccmsitp2884 2 жыл бұрын
Veeery nice! 👍
@VinayKumar-ki5fd
@VinayKumar-ki5fd 2 жыл бұрын
Very gooood :)
@amrosamy8232
@amrosamy8232 2 жыл бұрын
I'd prefer returning a concrete type instead of an abstract interface "IResult" It would be better for swagger documentation
@leonardoformaggi7614
@leonardoformaggi7614 2 жыл бұрын
You can use the .Produces() method overloads to generate your swagger appropriately.
@amrosamy8232
@amrosamy8232 2 жыл бұрын
I'd say returning Result can be an option as well.
@leonardoformaggi7614
@leonardoformaggi7614 2 жыл бұрын
It is. Although with Produces you can specify different responses for different status codes, if you need to. Whatever is best for you scenario.
@miindgame
@miindgame 2 жыл бұрын
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 2 жыл бұрын
One handelr per request not one handler for all requests
@miindgame
@miindgame 2 жыл бұрын
@@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! :)
@volodymyrliashenko1024
@volodymyrliashenko1024 2 жыл бұрын
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 2 жыл бұрын
There's always eShopOnContainers.
@suleymanov1990
@suleymanov1990 2 жыл бұрын
Also CleanArchitecture template and NorthwindWindTraders from Jason Tyler.
@copycatzen
@copycatzen 2 жыл бұрын
Isn't AddMediatR registered as scoped by default already?
@nickchapsas
@nickchapsas 2 жыл бұрын
Pretty sure it’s transient
@Arkensor
@Arkensor 2 жыл бұрын
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 2 жыл бұрын
Extension methods are what I use for that
@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
@andreasandersson7685
@andreasandersson7685 2 жыл бұрын
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.
@maacpiash
@maacpiash 2 жыл бұрын
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 2 жыл бұрын
No there isn't, as long as you injecting everything through the handler's parameters
@joephillips6634
@joephillips6634 2 жыл бұрын
thanks dad
@adrian_franczak
@adrian_franczak 2 жыл бұрын
what about fluent validation in this pipeline?
@nickchapsas
@nickchapsas 2 жыл бұрын
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
@sergiik2168
@sergiik2168 2 жыл бұрын
So handlers doesn't contain business logic and these are more like proxies to business layer. And what is the point to add additional proxy-layer, when instead of this you could directly call services from MapRoute methods? This looks like over-engineering.
@user-iv7uj7lx8n
@user-iv7uj7lx8n 2 жыл бұрын
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 2 жыл бұрын
Put your Request and RequestHandler in the same file.. bingo... Navigate to requests..
@letifere
@letifere 2 жыл бұрын
I do the same as Jo Bumble, put Handler and request objects in the same file.
@adrian_franczak
@adrian_franczak 2 жыл бұрын
What if I want send POST request with body?
@nickchapsas
@nickchapsas 2 жыл бұрын
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
@IgorChistruga
@IgorChistruga Жыл бұрын
Hey Nick - is the sourcecode somewhere available?
@nickchapsas
@nickchapsas Жыл бұрын
It is. Check the first line in the description
@anthonylerouge9900
@anthonylerouge9900 2 жыл бұрын
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 2 жыл бұрын
The Results and TypedResults method contains all the statues you might need. Results.NotFound(), Results.BadRequest() etc
@anthonylerouge9900
@anthonylerouge9900 2 жыл бұрын
@@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 2 жыл бұрын
it works well with the happy path but what about error handling?
@nickchapsas
@nickchapsas 2 жыл бұрын
@@anthonylerouge9900 Like I said, you just handle the error in the handler and return the appropriate response.
@dmisterb
@dmisterb 2 жыл бұрын
Hey Nick! Could you make some videos about System.Reactive?
@nickchapsas
@nickchapsas 2 жыл бұрын
I have one coming in September or October
@Doctor.Livesey
@Doctor.Livesey 2 жыл бұрын
what if request used several services to make result?
@nickchapsas
@nickchapsas 2 жыл бұрын
No problem at all. Most services do
@bjarkeistruppedersen8213
@bjarkeistruppedersen8213 2 жыл бұрын
Does this work with the new MapGroup they added to v7?
@nickchapsas
@nickchapsas 2 жыл бұрын
Yeah can't see why that might be a problem
@marcomannarino7930
@marcomannarino7930 2 жыл бұрын
Nice:)
@roko567
@roko567 2 жыл бұрын
I have yet to see a single good reason to go "cleaner" than the MVC patttern
@carldaniel6510
@carldaniel6510 2 жыл бұрын
I'm curious - Many of your videos are about writing APIs, yet in my 40+ years as a developer, I'd estimate that creating APIs (or their 40 years ago equivalent) constitutes far less than 1% of my development. Is modern development really so slanted towards creating APIs? I don't mean that at a criticism, but as a genuine question.
@nickchapsas
@nickchapsas 2 жыл бұрын
Oh yeah. In my past 5 years working exclusively with microservices I've probably worked on at least 70-100 APIs and then long running services and serverless lambdas on top of that. It's probably not something you'd do in oldschool enterprise but if you're working in microservices it is all you do. Well, that and also making sure the architecture is resilient.
@giovani5586
@giovani5586 2 жыл бұрын
Interesting, what do you work or used to work with? I guess 80% of my work is doing APIs
@PelFox
@PelFox 2 жыл бұрын
I want to jump into this one. I'm quite early in my career, I've worked for about 4 years now. For my job I havent worked with anything but APIs, serverless, message brookers and databases. With a few exceptions of Blazor or Razor pages for simpler internal tools and admin dashboards. Majority of apps I work with are SPA using React or Angular with a .NET API. If you have worked for 40 years and APIs are just 1%, what kind of apps are you building and for what industry? I guess desktop apps were quite common previously? My employee just wants APIs and integrations so I just keep delivering that ¯\_(ツ)_/¯
@StuartBlackburn
@StuartBlackburn 2 жыл бұрын
I'm pretty much 100% of the time writing APIs now for the last 4 years, out of a 20+ year career.
@carldaniel6510
@carldaniel6510 2 жыл бұрын
@@giovani5586 Desktop apps; back-office data processing apps; embedded code - that sort of thing. I've worked in medical diagnostics, avionics, television special effects, banking, financial services, robotics. Pretty much no microservices.
@weluvmusicz
@weluvmusicz 2 жыл бұрын
What about Swagger with this approach?
@nickchapsas
@nickchapsas 2 жыл бұрын
You'd have to add the fluent extensions "Produces" on the MediateXXX calls to describe the endpoint's responses
@bad-at-art-games
@bad-at-art-games 2 жыл бұрын
Isnt this becoming closer and closer to Controllers every Time?
@nickchapsas
@nickchapsas 2 жыл бұрын
You can handle multiple requests in a single controller violating single responsibility. This is a better structure
@PelFox
@PelFox 2 жыл бұрын
@@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 2 жыл бұрын
@@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 2 жыл бұрын
@@nickchapsas Never said it was good, just said it is possible. Nothing forces you to add multiple action methods in a controller.
@mana20
@mana20 2 жыл бұрын
Is it hard to Unit Test using mediator? I know I ran into some issues with CAP handlers
@nickchapsas
@nickchapsas 2 жыл бұрын
I never had a problem unit testing it
@akzual50
@akzual50 2 жыл бұрын
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.
@metaltyphoon
@metaltyphoon 2 жыл бұрын
At 1:55 you said "that's not really testable" why is that? If you business logic is just used in via an API, then why can't you just use WAF? The hole video boils down to allowing you to do "easier" testing from whatever handler goes inside `app.MapGet` and not much more while introduction extra libraries. Minimal APIs is a nice break from controllers and align more with flask / express / golang. It's a breath of fresh air and now we are just going to bloat it again?
@nickchapsas
@nickchapsas 2 жыл бұрын
WAF is used for integration testing. I should have said that it's not "unit testable". The video isn't about testing though. It is about structure. It is way cleaner to have your request's handling logic in a single specialized class that does that thing only and it helps with code organization.
@metaltyphoon
@metaltyphoon 2 жыл бұрын
@@nickchapsas I understand the video is not about testing but about structure. You can still get that the structure you had without introducing mediatr right?
@fatihcihanhizlikan1427
@fatihcihanhizlikan1427 2 жыл бұрын
That's Refit. 😀
@HakunaMatata225
@HakunaMatata225 7 ай бұрын
still understand whats the point of using MediatR or what problem it solved!! you could had done this without MediatR !!!
Clean Message Bus Consumers with MediatR in .NET
27:20
Nick Chapsas
Рет қаралды 50 М.
How slow is MediatR really?
15:51
Nick Chapsas
Рет қаралды 60 М.
Players vs Corner Flags 🤯
00:28
LE FOOT EN VIDÉO
Рет қаралды 90 МЛН
Fix Your Controllers By Refactoring To Minimal APIs
14:56
Milan Jovanović
Рет қаралды 41 М.
You are mocking the HttpClient the wrong way
13:56
Nick Chapsas
Рет қаралды 49 М.
The New Option and Result Types of C#
15:05
Nick Chapsas
Рет қаралды 71 М.
A new way to build CLEAN and FAST APIs in .NET
17:52
Nick Chapsas
Рет қаралды 92 М.
What is Span in C# and why you should be using it
15:15
Nick Chapsas
Рет қаралды 256 М.
Automatically Register Minimal APIs in ASP.NET Core | REPR Pattern
11:55
Milan Jovanović
Рет қаралды 14 М.
The 2 MediatR features people don't know about but should
13:48
Nick Chapsas
Рет қаралды 34 М.
The Magical Pattern to Organize .NET Minimal APIs
9:06
Gui Ferreira
Рет қаралды 9 М.
Don't Use Polly in .NET Directly. Use this instead!
14:58
Nick Chapsas
Рет қаралды 64 М.
Should I Create A Minimal API Or Full API?
7:40
IAmTimCorey
Рет қаралды 37 М.