Validation using MediatR's Pipeline Behaviors and FluentValidation | Clean .NET Core

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody I'm Anakin this we're gonna take a look at pipeline behaviors in mediator this video is a continuation of the previous video when we just introduced mediator and CQRS nor a speed non core API so this is just a follow up to see how we can actually add something like validation or logging in a very elegant way using mediator in this field I'm going to only focus on validation but logging will basically use the exact same logic let's take a look at what the pipeline behavior is in mediator so in mediator here's me and here is the logic and this logic is part of a handler now whenever I sent a request the handler takes that request and it returns a response back that's the basic model and what we did is we broke this request to a query and a command so come on coming in response comes out now this logic is just anything in the handler but what happens if you want add validation you could j-just in the handle method just add a validate method call and then validate the command this could work but the problem with that is that now our handle model has also the validation and the logic and we don't necessarily want to do that what we can do instead is that if I remove this logic I can actually see mediator as sort of a pipeline so let me create this so this is where my request cannot go in and come out but instead of having this single piece of logic I'm gonna instead move that logic here logic and then I'm going to have three levels here the first one is going to be the pre processor the next step will be a delegate calling the next thing in the pipeline some sort of a middleware innocence and the last step is the post step anything after my logic and the way this works is request comes in it goes to the pre level the pre level will call the next in the next will go to the next thing in the pipeline basically the logic the logic comes back and then the post can do other things after that and then the result goes back to the user and the cool thing about this is that you could very much just take the logic and move it back and add another just same thing here where you have the pre the next and the post and you can again have things go to the pre call the next girl to the post this causes this is calls that this the whole thing this whole block represents the pipeline and this pipeline essentially is a bunch of layers that allow us to do different things on different levels and what are we going to do in this specific scenario is we're gonna go back to the previous state and what we're going to do is on this pre step we're gonna say validate and we're going to use fluent validation for this one I already have a video infinite values you can find it in my channel but that's what we're basically gonna do so in the pre step we're gonna validate go back if the validation fails then we're gonna return earlier we don't even go to this level but if it's fine then we're gonna do all the logic and return we're not gonna use the post for anything but if you wanted to use that you could and we have sort of three levels on this we have the pipeline behavior which is what we're going to use and then we also have preprocessor behavior which focuses on this pair or post process or behavior which just focuses on this pen but we are going to go fold the whole thing so let's just jump right into the code this video is part of my clean HP dual core series so if you don't want to miss any episodes please subscribe this our modification well so here exactly what we left off in the previous video the first thing I'm gonna do is I'm gonna add two packages in the project the first one I'm gonna add is fluent validation and the next one I'm gonna add is actually the fluent validation package extension about dependency injection I'm not going to use the spirit core at packages instead what I did is I made an extension method here which will essentially catch any validation exceptions thrown as part of my pipeline and convert them into this error model and return a bad request you shouldn't necessarily do this in your actual applications the only reason why I'm doing it is because I am actually sharing these common which is essentially the main model in my controller and I didn't want just separated because there would be a disconnect from the previous video but ideally you should not be doing this you should have a request object mapped that to a command and then send that command to the mediator but just for demonstration purposes I'm keeping this so with those two packages included I'm gonna go ahead and create a couple of folders the first one I'm going to create it's a directory called validation and the next one is a directory called behaviors well that's actually a bad name let's say pipeline behaviors code so with these two things out of the way the first thing I want to add is actually let's go with the validation first so we're gonna create a class and this class will be the name of the command we want to build it against we only have one command so we're gonna just use this to create customer order command so it could be the name and then validation new class called create customer or the command validator and this will be an abstract validator of type the command we wanna validate and now we're not created I'm going to create a constructor and I'm only going to add very simple validations because I don't wanna go in depth on what fluent validator is this is about the pipeline behaviors so when I get all the validation stuff out of the way first so I'm just gonna say rule 4 and I want to add a rule for the customer ID and they're along an ad is it should not be empty and then I'm just gonna copy that and at the exact same rule for Product ID you could inject anything you want here this will work with the dependency injection and you could just validate that the customer with this ID exists and that the product we decide exists and you can do all sort of custom stuff with fluent validator but I'm going with simple for now just gonna do this now go ahead and close this and this works well and now that we add this I want to register my validators in my dependency injection so I'm gonna say services dot add validators from assembly I'm gonna say type of startup like with it before and assembly and this will register automatically anything that's an eye validator an abstract validator in the DI container to be injected so that is done now the next step is to create the pipeline behavior so let's create a pipeline behavior folder and create a new class and I'm going to name this class validation behavior now you might have seen the specific class in Stack Overflow answers or in blog posts this is not a new class it's probably the most common example alongside logging to present this picture so I'm just going to use the same thing essentially and this will be a behavior that will accept a team of requests and return at a response it's exactly the same as if you go into our handlers essentially the exact same thing something comes in something comes out but instead of and implementing the I request handler interface we are going to be implementing the I pipeline behavior interface and this interface requires a request in response and it also requires that we say that where the request is an I request of type T response and this only has a single method which is the handle method very similarly to how the handler has the having method but the extra thing that this method has is this delegate here this next and this is if you remember the diagram the thing I was talking about the thing that it will actually push things to the next thing in the pipeline so essentially everything that happens before this call is pre the behavior and everything after that is post the behavior is post everything after the pipeline code in this specific use case when you're going to use the post so can just say return here but we are going to use the pre to other world letters so what I need is I need to have a private reading Li field of type I in numerous of type I validator of type T requests to essentially give me every validator in my di container for this cific requests and i'm just going to name this validators and i'm gonna inject it from the constructor so I have my eval data here but these are all my validators so there are few steps I need to take in my logic for the validation first I need the context so I'm going to say new validation context and this requires request and then I need to find all the failures so first I'm gonna say failures equals validators dot select and then validate this context the context that contains the specific request I won't validate it and then the validation will take place and I need to do a select many to get the result any errors if any and to check that the errors are not null and I actually have some errors I'm gonna say check for anything that is not null so check for errors that exists and then we're gonna to list this to trigger this and here I need to say if failure is dot any then throw a new validation exception with all the failures I'm gonna enjoy that properly and now obviously people can say and you can say what we might be thinking hey make validation Hennig throwing exceptions are expensive and I agree you should not be throwing exceptions to do validation but for this example to show you how this works I'm going to throw an exception in your highly efficient highly performant system you might not want to return at a response but you might want to return a result of T response and instead of throwing here you would return the bad version of that result not the good version and then in your pipeline you can have a middleware that says ok translate this into a bad request response I'm doing this with this extension method I showed you before just for simplicity but you might want to go with a different approach and now with this out of the way what I to do and the last thing I need to do actually is to just register this behavior in my di container so I need to say services dot ad transient because I want this to run on essentially every time it's requested I'm gonna say type of I pipeline behavior and I'm gonna just put a comma here I'm gonna specify the types and then instantiate this with the type of validation behavior we find that here and again comma so register this for any T request and T response and with any T request into response and essentially that said the code is very very minimal and the you can find the code for the video in the description down below I'm just gonna run this to show you how it works I'm gonna stick a few breakpoints here I'm gonna go in the controller is it the right controller I think it's a right controller this is totally not the right controller I'm gonna go in the oldest controller and we're gonna put the breakpoint here so this is a create order endpoint where we add our validation and then I'm gonna add the breakpoint here and they get all orders where we have no validation at all and I'm also going to add a breakpoint in my validator here maybe maybe in the constructor so I have this so if I go and create an order here you can see that the controller is being hit first so the command has not been validated it has not hit this breakpoint which means that there is nothing happening at this level when the requests coming in and now I'm going to send it to the mediator and as you can see the first thing that it's being hit is the validator and it's going to go through the validation check if it matches any rules that I have and after that but the behavior is done it's gonna go through the failures find none it's gonna call the next thing in the middleware and the next thing and then we were in this specific scenario was the handler so we got a response back and in fact if you want to see this again with a breakpoint on the handler I can actually do this to show you that it actually calls it in the right order so now I have one here if I just click that button again first thing goes in the controller second things validator third thing handler and then response so this is all working great now if the product ID is zero let's see what happens in this scenario so first controller then validator these validation passes but this one doesn't pass so it goes through the validation behavior finds the fail and throws the exception and with the exception thrown we are getting a bad request product ID product ID must not be none so our validation is actually working and keep in mind this is the main level validation this is not API level validation which is what we want and just to show you that there is no validation in anything else because well we did not set it up I can just say give me all the orders and this just goes in the controller there is no behavior to handle that so it just returns all the orders so very simple very cleanly we can just create the validation class specify the command over the query you want to validate and you can add all your domain level validation here which is a very clean way it can be confusing for people jumping in saying ok where is this validation coming from but once you explain that you have this separation of your validation in your main logic it becomes way more easier to work with it and and literally easier to test and we're gonna see testing in the future video of this series you can find the code for all this in the description down below that's all I have for you for today thank you very much for watching special thanks to my github sponsors for making these videos possible if you want to support them as well you're gonna find the link in the description down below leave a like if you liked this video subscribe for more content like this ring the bell as well and I'll see you the next video keep coding
Info
Channel: Nick Chapsas
Views: 46,795
Rating: 4.9590092 out of 5
Keywords: coding, asp.net, .netcore, dot net, C#, how to code, tutorial, asp.net core, csharp, rest api, development, software engineering, dev, microsoft, .net core, asp.net core 3, cqrs, mediatr, design patterns, clean architecture, clean code, asp.net core api, pipeline behaviors, fluentvalidation, validation, pipeline, middleware, mediator, dotnet, .net
Id: 2JzQuIvxIqk
Channel Id: undefined
Length: 15min 2sec (902 seconds)
Published: Thu Dec 05 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.