Getting Started With MediatR and Vertical Slices in .NET

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody I'm Nick and in this video I'm going to show you how we can take an existing code base in Aspire core that isn't using mediator and migrated to use it now this video will focus on the how not on the why I do have a video already if you want to know why we're using mediator in the first place and what's the benefit of using it so I'm going to put it on the dropper corner of the screen and the description Down Below in this video we're just gonna focus into the process of adding it into the system and explaining some things as we go and we're gonna do that using more of a vertical slices mindset and also hint towards a cqrs approach if you like our content and you want to see more make sure you subscribing this notification Bell and for more training check out nickjamses.com alright so let me show you what I have here I have a simple web API called movies API and this API as the name implies is used to store and retrieve movies so if I just quickly run it just to show you what we're going to be dealing with here I'll have post one with all my API requests I can list a movie I'm gonna list the classic movie Nick the Greek that came out this year and as you can see a movie is created I can take this ID of the movie and retrieve it using its ID but this movie also has a slug which is like a URL friendly version which I can also use to retrieve that movie of course if it is invalid you're gonna get a 404 I can list all the movies in the system I can update a movie if I want to update only works with the IDS I would have to copy that paste it here and I'm saying oh no actually this movie came out last year I also have validation so if I try to update a movie Into the Future that is invalid that I'm getting an error if I try to update the movie it doesn't exist I'm going to get an error and I can also just delete a movie and delete will return okay if it was deleted not found if it wasn't found with deleted so let's see how this movie's API is actually implemented and see where we're gonna start and how we're gonna start migrating to mediator now I should point out this API is using sqlite because you might want to just grab the code from the description down below and use it so you can see all the objects in all the tables here and let's take a look at what we have so I have a contracts folder this includes all of my API contracts that are eventually being converted into my domain model which is that movies object then I have all my database related stuff in here and I have all my movies related stuff here so the movie Object itself is here the movie repository is here I'm using a repository button here to access sqlite my controller is here so all the control related things are here service and then while that we're focusing on a more vertical slice approach where my movies feature is isolated with all its concerns in here and then I have some validation of things for example this validation model now the way flow works is you walk into the controller and then we push the thing into the service the service will then call the repository and do some validation on top of that and we're using fluent validator for that and then eventually it's going to call into the repository now for many people the benefit of adding mediator in this approach is that you can actually isolate each individual action and not have this master service object that has to know about everything for example why does the get endpoint get by slack or get by ID or even the get all or delete know about the existence of the validator in the first place because we inject that through the Constructor well it shouldn't because it's not using it but that is one of the drawbacks of having everything in here in this tightly coupled way and then we have to explicitly inject that movie service into the controller what mediator will allow us to do is actually separate each action into its own class with its own dependencies and to start what we need to do is actually add mediator now since mediator 12 you no longer need to have an extra dependency injection nougat package because everything has been Consolidated into that mediator package so you don't need that if you want to have dependency injection now it is built in and out we have this in place what we're planning to do is completely remove this movie service and have a Handler per action where the controller accepts the requests and sends a request into an action and by the way if you're using minimal apis the same rule applies you would have an endpoint that patches the request into a Handler so let's take a look how we can Implement that the first thing I'm going to implement is the create endpoint and as you can see what happens in create is we get the request and then we map it into a movie we get the movie we validate it if it is invalid we return a validation failed object which is then being mapped to a response but if it was valid then we just create the object and return the movie to be shown into that 201 response body so let's start with create and I'm going to focus on that vertical slice approach where I'm just going to say that anything related to creating a movie will go here so I'm going to create a create movie class and that is it now the classes I'm going to have in here are not gonna be called create movie instead I'm going to have a create movie command a command indicates an action that mutates the system in some way and again focusing on that cqrs approach where we separate our queries from our Command queries are pure they don't create any state commands will mutate the state now what I'm actually going to do is utilize a record so I don't need to have a class I'm going to use a record which again is still a class behind the scenes but I'm going to have my parameters here in a compact way so what I have is the title and the year of release and that is it and then this record needs to implement the I request interface of mediator to indicate that this is a request that actually returns a specific type in this case the type is a result which can be either a movie to indicate success or a validation failed to indicate failure and that is it let me just new line this so you can say it even better and that is how many Creator in its simple request response approach works you have requests you send them through the mediator Pipeline and you get a response back you don't exactly know where it went all you know is that you sent a request that looks like this and it has a set response shape and you get that back and you process it and by the way in this result I have here is a bit of a discriminated Union on something that can be a success or a failure of some sort so that's why I'm using that here and not I have the command I need a Handler for that command so I'm going to create a public class create movie Handler here we go now this will need to implement the I request Handler interface and we're going to have the first parameter be the command itself and the second parameter be the response type so this is a Handler that accepts this specific command and returns this return type and we're going to implement missing members and that's how that looks so what does create need it needs the movie repository and the movie validator so just gonna go ahead and inject them here faster repository and then the validator so both things are injected from The Constructor and I can now use them in handle now for handle I'm just going to copy what I had in the service because remember we are replacing what we had in the service now into this handle with mediator and of course mediator is async only and async first as well so we can have it here but since we no longer have that movie that we had from the mapper we can actually simply just create it here or move that into a mapper we don't need to explicitly do this for every object you can have your own mappers in my case I wrote them up as myself because I don't like using something like Auto mapper but with bigger objects you can use it just make sure you do not put any business logic in there so now I have that in the exact same code but now the great thing about this is that only the things I need are injected in here nothing more nothing less and if I wanna edit something I only edit this class that is solely responsible for this action and nothing else now with creating place let to get and the process is the same but in this case get movie will actually be a query because it is that pure form of a request that doesn't mutate any state again a record get movie query and I'm gonna have an I request that returns and now I will move because a movie can exist or it might not exist and this query in this case has a single parameter called ID o slog because you can search something by ID or you can search it by slide same thing as before we're gonna have a get movie Handler using those same parameters as before we're gonna implement the missing members and we can only inject what we need in this Handler but the great thing about this is that I don't need that validator that I had in that service in this case so I can only inject the repository which is really what I care about and by the way if you're doing cqrs where you actually separate your repositories to your query based repository and your command-based repository then this will allow you to only inject what you really need in this Handler in terms of filamentation the process is the same I turn this into async and then I have my check whether it's good or not and then a return appropriately and that is it now to wire these handlers up because as you can see nothing really explicitly uses them all I need to do is go to the program.cs and I can say builder.services.add mediator and the way this works now is you have this configuration action and you can say register services from assembly containing a specific type the type we want here is the program.cs but it can be anything in many cases you might actually want to create a specific type to use as an assembly marker to mark an assembly all this is really does is it lets mediator know that hey if you see anything that is a Handler or in some cases a pipeline or behavior in this assembly please register it so now with that in place I can now go into my controller and I'm gonna remove this movie service completely and I'm gonna comment out the get all and the delete mainly because I just want to show you how simple now it is to inject the imediator interface initialize that from the Constructor and that's going to be registered as part of that add mediator call and then all I need to do here is we no longer need to know exactly what's going on behind the scenes all we need to say is that okay goodbye movie goodbye this and now what we need is a command we're going to send into mediator to be handled by some handle responsible for that result so I'm gonna say command equals new create movie command with that title and year of release and then we're gonna take that command and we're gonna send it over to mediator so I'll wait mediator dot send and we're gonna just say take that command give it back eventually and we're gonna process it and now the difference in handling here is that I actually need that movie Object to get the ID and the object to map it into the response body so I just handled it here from that match method which is part of that result method that I have over here and then just map it into that response and return it to the user and I'm gonna do the same with get I'm going to remove all that the controller doesn't need to know anything all it needs to have is that get movie query with that ideal Slug and it's going to send that query over to mediator so now we're in place I'm gonna go ahead and just run my API remember only get my ID or Slug and create works so what I'm going to do is just go over here and I'm going to go ahead and create a new movie Nick the Greek 2 the sequel which came out on the same year so as you can see the movie was created and what I'm going to do is add a breakpoint here to show you exactly what's happening so I'm gonna create the third movie as well why not at this point so the breakpoint is hit we're getting that API contract over here that we map that into a command and then that command is send into mediator now here's one of the biggest problems with mediator you cannot step into the send method because what happens behind the scenes is there's a dictionary that matches requests with handlers so what you need to do if you want to debug it which is a bit of a pain is to know which Handler is responsible for handling it at a break point here and then step over and that way you're gonna land into the Handler that's one of the biggest criticism but I can live with that so we have the movie we check the validation result it should be valid so it is valid and then we go all the way into the database we created into the database in that sqlite and then we return it back and we show it to the user and if I want to get it by ID I can go here and I have a query in place so I can get it either by ID or by Slug and things like not found still work now because everything else use the same principles so get all update and delete is just the same I'm just gonna do them off camera and add them into the system here you go so get all is here only injecting the repository update is here with the ID as well which we are mapping from the controller and then delete is here as well now you might be looking at this and saying oh Nick you just added so many new class files and so many things in here now to do the exact same thing you were doing before why did you do that well you would be right if we were just to leave this as it is if you just add mediator and that is your outcome and that is your finished product then you didn't really gain much arguably you lost something because now you have all these handles that are being instantiated By Request wasting more memory in your application but mediator has some awesome mechanisms and features built in that will now allow you to completely supercharge your API and your Aspen core project and if you want to know more about them Please Subscribe because I will be making a series about how we can take this exact code base to the next level however if all you wanted was a quick getting started guide with mediator that should be more than enough you know how to create queries you know how to create commands you don't have to send them over and you know how to use them in a real API but what do you thing do you agree with the criticism that mediator gets and have you used it in the past leave a comment down below and let me know well that's all I had for you first video thank you very much for watching special effects to my patreon for making videos possible if you want to support us ready to find the link description down below leave a like if you like this video subscribe and I'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 37,079
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, .netcore, dot net, core, C#, how to code, tutorial, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, dotnet, .net, .net 7, mediatr, mediator, vertical slices, vertical slice architecture, asp.net core, asp.net core api, .net mediatr, mediator c#, mediatr C#, Getting Started With MediatR and Vertical Slices in .NET
Id: Ve__md8LeDY
Channel Id: undefined
Length: 14min 20sec (860 seconds)
Published: Mon Apr 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.