Write cleaner APIs in .NET 7 with MediatR

แชร์
ฝัง
  • เผยแพร่เมื่อ 2 ต.ค. 2024
  • 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 ปีที่แล้ว +302

    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 ปีที่แล้ว +1

      wait what? :D

    • @barloc2
      @barloc2 2 ปีที่แล้ว +14

      Apologies accepted. We are all human beings, mistakes can happen.

    • @pdevito
      @pdevito 2 ปีที่แล้ว +4

      Ruined

    • @redouane5626
      @redouane5626 2 ปีที่แล้ว +14

      you should apalogize for naming it MinimalatR 😑

    • @dungimon1912
      @dungimon1912 2 ปีที่แล้ว +1

      huh?

  • @barloc2
    @barloc2 2 ปีที่แล้ว +47

    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 ปีที่แล้ว +22

      I MISS CLICKED THE BUTTON DON'T JUDGE ME

  • @SamueleFurnari
    @SamueleFurnari 2 ปีที่แล้ว +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! 💪

  • @qwer1234cvb
    @qwer1234cvb 2 ปีที่แล้ว +8

    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 ปีที่แล้ว +23

    To make your code even neater, remember you can use records instead of classes for your MediatR requests.

    • @Suriprofz
      @Suriprofz 2 ปีที่แล้ว +3

      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 ?

  • @TimurMANDALI
    @TimurMANDALI 2 ปีที่แล้ว +3

    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
    ));
    }

  • @jamesmussett
    @jamesmussett 2 ปีที่แล้ว +12

    I recommend forwarding the CancellationToken to mediator from the delegate, otherwise it will just use the default CancelationToken in the handler.

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว +5

      Yeah without passing the CT from the handler's patameter's to the Send call, the cancellation won't be triggered

    • @sergiik2168
      @sergiik2168 2 ปีที่แล้ว +1

      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 ปีที่แล้ว +1

      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?

  • @benjamincharlton3774
    @benjamincharlton3774 2 ปีที่แล้ว +6

    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.

  • @Dimich1993
    @Dimich1993 2 ปีที่แล้ว +1

    I cannot read MinimalatR correctly either. :D
    Please support Ukraine guys!

  • @digitalhome6575
    @digitalhome6575 2 ปีที่แล้ว +3

    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 ปีที่แล้ว +3

    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)

  • @CarmenSantiNova
    @CarmenSantiNova 2 ปีที่แล้ว +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.

  • @pcapcapca
    @pcapcapca 2 ปีที่แล้ว +6

    I'm disappointed with that age of 60

  • @brud90
    @brud90 2 ปีที่แล้ว +1

    hmmmm... It looks like F# and Giraffe 😉

  • @victor_pogor
    @victor_pogor 2 ปีที่แล้ว +5

    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 ปีที่แล้ว +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 ปีที่แล้ว +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.

  • @amantinband
    @amantinband 2 ปีที่แล้ว +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 ปีที่แล้ว +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 ปีที่แล้ว +1

      @@nickchapsas there is also the HttpContextAccessor as well

  • @harbor.boundary.flight
    @harbor.boundary.flight 2 ปีที่แล้ว +1

    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 😅

  • @AngusMcIntyre
    @AngusMcIntyre 10 หลายเดือนก่อน

    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.

  • @fred.flintstone4099
    @fred.flintstone4099 ปีที่แล้ว

    This is pretty dumb. You can test minimal API, not with unit tests but with integration tests. What you did with using MediatR and implementing handlers is basically just like implement a controller but with more boilerplate code and dependencies, so this is pretty silly, it is much better to just create controllers.

  • @HakunaMatata225
    @HakunaMatata225 7 หลายเดือนก่อน

    still understand whats the point of using MediatR or what problem it solved!! you could had done this without MediatR !!!

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

  • @karthiksrivatsa8243
    @karthiksrivatsa8243 2 ปีที่แล้ว +1

    We can generate swagger documentation as well and also use fluent validation. Combining all these will definitely make cleaner API.

  • @Suriprofz
    @Suriprofz 2 ปีที่แล้ว

    minimal api seems so hackish, like it's added only to allow more node(express) developers te join microsoft here..

  • @VijayKumar-wy9ku
    @VijayKumar-wy9ku 10 หลายเดือนก่อน

    Isn't it increasing the boiler plate? You are gonna have n handlers(classses) for n endpoints.

  • @GleichCraft
    @GleichCraft 2 ปีที่แล้ว +6

    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 ปีที่แล้ว +9

      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

  • @FraserMcLean81
    @FraserMcLean81 2 ปีที่แล้ว +1

    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.

  • @kippie86
    @kippie86 2 ปีที่แล้ว +1

    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 ปีที่แล้ว +3

      All [FromXXX] attributes work inside the request

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

  • @bryanlewis3643
    @bryanlewis3643 2 ปีที่แล้ว +1

    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 ปีที่แล้ว +4

      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

  • @ja-rek8846
    @ja-rek8846 ปีที่แล้ว

    Why people so love to have a god object in they project as madiatR?

  • @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 ปีที่แล้ว +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.

  • @metaltyphoon
    @metaltyphoon 2 ปีที่แล้ว +1

    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?

  • @jonholt8429
    @jonholt8429 2 ปีที่แล้ว +1

    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

  • @idzyubin720
    @idzyubin720 2 ปีที่แล้ว +1

    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 ปีที่แล้ว +1

      Nick already talked about the performance of MediatR in this video: th-cam.com/video/baiH3f_TFfY/w-d-xo.html

    • @idzyubin720
      @idzyubin720 2 ปีที่แล้ว

      @@kippie86 thanks, I’ve seen this video yet

  • @georgepagotelis
    @georgepagotelis ปีที่แล้ว

    I couldn't attach EndpointRouteBuilderExtensions methods such as WithTags, etc. Example:
    app.MediatrGet2("test/AsParameter/{name}")
    .WithTags("*MediatR")
    .WithOpenApi();
    So over my lunchtime, I changed the method so it would. Have I mistaken something as dropping off EndpointRouteBuilderExtensions has those methods but WebApplication doesn't.
    public static class MediatrExtensions {
    //public static WebApplication MediatrGet(this WebApplication app, string template) where TRequest : IHttpRequest {
    public static IEndpointConventionBuilder MediatrGet2(this IEndpointRouteBuilder endpoints, string pattern) where TRequest : IHttpRequest {
    return endpoints.MapGet(pattern, async (IMediator mediator, [AsParameters] TRequest request) => await mediator.Send(request));
    }
    }

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

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

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

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

  • @dropsonic
    @dropsonic 2 ปีที่แล้ว +1

    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

  • @jairgza
    @jairgza 2 ปีที่แล้ว

    As far as I can see mediatr only knows about ExampleRequest, How mediator knows which handler instantiate and run ?

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

  • @AizenSousuke92
    @AizenSousuke92 ปีที่แล้ว

    anyone tried this in docker and it works?

  • @endmrx
    @endmrx 2 ปีที่แล้ว

    Thanks for the news!
    Minor: await Task.Delay(...); → await Task.CompletedTask; ?

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

  • @jonathanperis3600
    @jonathanperis3600 2 ปีที่แล้ว

    Can we have IResult out of AspNetCore project to build this inside a shared library?

  • @taufikdev88
    @taufikdev88 ปีที่แล้ว

    love the way you create an extensions class for registering everything

  • @Tof__
    @Tof__ 2 ปีที่แล้ว +1

    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.

  • @bernardo44250
    @bernardo44250 2 ปีที่แล้ว

    I didn't know this video existed! Thanks bro! Really grateful.

  • @wojciechwilimowski985
    @wojciechwilimowski985 ปีที่แล้ว

    You made the middle ground between classic and minimal APIs - minimal controllers!

  • @RuslanSafroniuk
    @RuslanSafroniuk ปีที่แล้ว

    Hello! How about put request with first parameter from route and second parameter from body?

  • @roko567
    @roko567 2 ปีที่แล้ว

    I have yet to see a single good reason to go "cleaner" than the MVC patttern

  • @joephillips6634
    @joephillips6634 2 ปีที่แล้ว

    thanks dad

  • @johnjosephsmith
    @johnjosephsmith ปีที่แล้ว

    Where is the source code for this. Unless I’ve missed it I can’t find on GitHub etc

  • @JonathanPeel
    @JonathanPeel 2 ปีที่แล้ว

    Is there a way to program minimal API on an interface, and then easily create a client, based on the interface?

  • @michaelfernandes6893
    @michaelfernandes6893 2 ปีที่แล้ว

    Is this not an example to couple youre frontend end to youre backend as a bad practice?

  • @kasperkadzielawa8658
    @kasperkadzielawa8658 2 ปีที่แล้ว

    Just a few more steps and you reinvent the classic controller class approach xP

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

  • @paulward8087
    @paulward8087 2 ปีที่แล้ว

    Reminds me of a CQRS approach I toyed with some time ago.

  • @samsonquaye9913
    @samsonquaye9913 ปีที่แล้ว

    How do we handle post?

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

  • @StigBrembo
    @StigBrembo 2 ปีที่แล้ว

    Love this! I changed your extension method a bit, so I could make use of the OutputCache in .Net7 too.

  • @scottatkinson7083
    @scottatkinson7083 2 ปีที่แล้ว

    Hey Nick, really enjoying the content so far. Just wondered what courses you're planning on bringing out soon?

  • @antonmartyniuk
    @antonmartyniuk 2 ปีที่แล้ว

    It looks nice, a Mediator way to structure the minimal APIs. Minimal APIs + MediatR = ❤️

  • @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 ปีที่แล้ว +4

      I will be making a video on that topic indeed

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

  • @spirits_
    @spirits_ 2 ปีที่แล้ว

    I recommend you never use MediatR for anything

    • @suleymanov1990
      @suleymanov1990 2 ปีที่แล้ว

      Is it any specific reason for this?

  • @fatihcihanhizlikan1427
    @fatihcihanhizlikan1427 2 ปีที่แล้ว

    That's Refit. 😀

  • @janvandenbaard5939
    @janvandenbaard5939 2 ปีที่แล้ว +1

    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 ปีที่แล้ว +1

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

  • @VinayKumar-ki5fd
    @VinayKumar-ki5fd 2 ปีที่แล้ว

    Very gooood :)

  • @realsk1992
    @realsk1992 2 ปีที่แล้ว

    Is there an elegant way to do validation with MediatR, without throwing exceptions for the validation errors?

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว +1

      This one is. You simply puth your validation logic in the MediatR pipeline and return the IResult bad request diretly from there

  • @DevonLehmanJ
    @DevonLehmanJ 2 ปีที่แล้ว +1

    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 ปีที่แล้ว +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.

  • @andrewalexopoulos921
    @andrewalexopoulos921 2 ปีที่แล้ว

    Great video as always! Nice usage of mediatr lib as well :)

  • @DarraghJones
    @DarraghJones 2 ปีที่แล้ว

    Isn't your weather forecast handler basically a weather forecast controller?

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว

      No it is a single controller action

  • @thespicycoder5583
    @thespicycoder5583 2 ปีที่แล้ว

    Nick, can you please do a mini series on Dapr

  • @tonongah102
    @tonongah102 2 ปีที่แล้ว

    Thanks bro that was really helpful

  • @ADSNGreenLife
    @ADSNGreenLife 2 ปีที่แล้ว

    Nick you are dam good man!! bravo

  • @copycatzen
    @copycatzen 2 ปีที่แล้ว

    Isn't AddMediatR registered as scoped by default already?

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว +1

      Pretty sure it’s transient

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

  • @framidox3757
    @framidox3757 2 ปีที่แล้ว

    You are a life saver! Kudos to you! You rock!!

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

  • @IgorChistruga
    @IgorChistruga ปีที่แล้ว

    Hey Nick - is the sourcecode somewhere available?

    • @nickchapsas
      @nickchapsas  ปีที่แล้ว

      It is. Check the first line in the description

  • @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 ปีที่แล้ว +1

      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

  • @pablocom
    @pablocom 2 ปีที่แล้ว

    Loving this new .NET 7 feature

  •  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 ปีที่แล้ว +2

      FE is my personal prefered and recommended way to build apis in .NET.

  • @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 ปีที่แล้ว +1

      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.

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

  • @Mikebutawski
    @Mikebutawski 2 ปีที่แล้ว

    This was just awesome! Thanks a lot!

  • @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! :)

  • @xian9029
    @xian9029 2 ปีที่แล้ว

    Very helpful..thanks a lot.

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

  • @bjarkeistruppedersen8213
    @bjarkeistruppedersen8213 2 ปีที่แล้ว

    Does this work with the new MapGroup they added to v7?

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว +1

      Yeah can't see why that might be a problem

  • @stevehoff
    @stevehoff 2 ปีที่แล้ว

    Hmmm not to be that guy, but model binding isn't exactly a radical new idea.

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว

      You are that guy Steve

    • @stevehoff
      @stevehoff 2 ปีที่แล้ว

      @@nickchapsas lol so I've been told.

  • @sigtermnull
    @sigtermnull 2 ปีที่แล้ว +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

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

  • @mana20
    @mana20 2 ปีที่แล้ว

    Is it hard to Unit Test using mediator? I know I ran into some issues with CAP handlers

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว +1

      I never had a problem unit testing it

    • @akzual50
      @akzual50 2 ปีที่แล้ว +1

      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.

  • @jercyshore
    @jercyshore 2 ปีที่แล้ว

    Java has left the channel

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

  • @Doctor.Livesey
    @Doctor.Livesey 2 ปีที่แล้ว

    what if request used several services to make result?

    • @nickchapsas
      @nickchapsas  2 ปีที่แล้ว

      No problem at all. Most services do