Validation Behavior | MediatR + FluentValidation | CLEAN ARCHITECTURE & DDD Tutorial | Part 8

preview_player
Показать описание


Follow me on 'em socials:

Today we'll create a custom MediatR validation pipeline that will validate our commands and queries using the FluentValidation library.

Give MediatR a ⭐:

Give FluentValidation a ⭐:

Related Videos:

#dotnet #csharp

00:00. Intro
00:34. Current app state
01:10. Pipeline behaviors 101
01:56. Implementing a RegisterCommand validation pipeline behavior
10:20. Implementing a generic validation pipeline behavior
17:02. Fixing the error response
22:09. How MediatR pipelines actually work
Рекомендации по теме
Комментарии
Автор

Hi Amichai! Greetings from Brazil!
I am so grateful for your series! I've been following this far and everything just gets better!! Congratulations! Content like this is very rare!

tiagohenrique
Автор

What?! Zero comments about the most beautiful part of this video?! 😍🐶 28:15

liordagan
Автор

Great content 👌 especially the ending part - Yes!. The pipeline behaviours are like class decorators which obeys the "O" in the SOLID principles - the class should be closed for modifications and open for extensions.

ugochukwuumerie
Автор

Hello great content. Thank you very much. I have read and seen a lot of content about command validation but I still can't find a reason that justifies so much over-engineering and so much complexity.
I can achieve the same thing by injecting a class that performs all the validations with less than half the effort and with the same result. what am i missing? Thanks in advance 👍

davidpccode
Автор

So let's go back to when I asked you why your Commands/Queries weren't your API contracts. You stated that you wanted to be able to change the commands/queries implementations without changing the contracts. Ok, fair enough.

However, now, you are validating the Command and not the request. So, when you return a validation problem it is possible you are defining a validation problem on a property that doesn't actually exist on the contract.

So, your RegisterRequest could have FullName which you map to First Name, Last Name in your command. Your validator finds the Last Name is empty and returns a problem that states, LastName is required or some such error. How is the client supposed to fix this, because he has no LastName property in his contract?

Am, I seeing this correctly, or did I miss something?

pilotboba
Автор

Thanks for creating awesome stuff. Please keep making videos on c#.

being_aslam_tiger
Автор

Thanks for this video. I was waiting for a good explanation of MediatR behaviors and validating. Can't wait for domain and application validaiton breakthrough :D

patrykk.
Автор

Instead of invoking a Dynamic Call Site by using the 'dynamic' keyword in '(dynamic)errors' (which is slow) the same effect is accomplished by a simple cast from an object reference:

'(TResponse)(object)errors'

I try to prevent to use the keyword 'dynamic' at all times when possible.

Jeroen
Автор

Well Done Amichai,
I am excited to fo find your course. it is truly helpful.
Actually, I did not use your Error0r library so I had some challenges in returning the exception errors and I used my approach.
Thanks for sharing.

KarwanEssmat
Автор

i wish i could be as good as you guys in software development world.

fakeITDevTeam
Автор

Finally, I'm very happy and great video

ariefmuhammadlubis
Автор

Will you cover unit testing of the handlers? I’m curious how do you test it with so implicit validation that is sctually done in runtime behind the scenes. Should we not test invalid inputs then?

msek
Автор

Hey Amichai, great content! I've got a question. Doesn't this go against DDD principle of keeping logic(validation in this case) inside entity classes and ValueObjects in the domain? Right now the domain has no knowledge of these validations

dennisdurairaj
Автор

I really enjoy the series. Have learned a lot from these series. Anyway, alt+z should toggle the words wrap automatically.

StandleyPeter
Автор

Thanks for the video. It's a little bit hard to read without word wrapping and big font.
if you could maybe close the files list or decrease font a little I think it would be much easier to undrestand.

mahditalebi
Автор

i don't know if it's just me but that final part with pipeline and Aggregate was so much easier for me when I learned this concept a while ago in js world working with rxjs .pipe(). YOu should probably rename 'pipeline' to 'behavior' when defining Aggregate reducer. Nevertheless, content is terrific as always, thank you Sir!

arthurfedotiew
Автор

the tutorials are really great, thanks a lot

ugursesen
Автор

Great video as usual. Just one thing, instead dynamic I've implemented in this way: First, I split Command and Query into 2 interfaces
public interface ICommand<TResponse> : IRequest<ErrorOr<TResponse>>
{
}


public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, ErrorOr<TResponse>>
where TRequest : ICommand<TResponse>
{
private readonly _validators;
public validators)
{
_validators = validators;
}
public async Task<ErrorOr<TResponse>> Handle(TRequest request, CancellationToken cancellationToken, next)
{
if (!_validators.Any())
{
return await next();
}

var context = new
var validationResults = await => v.ValidateAsync(context, cancellationToken)));
var errors = => result.ToErrors()).ToList();

if (!errors.Any())
{
return await next();
}
return errors;
}
}

Because, if I need ErrorOr in e.g. some behavior (logging or whatever) after next() to log something with this approach I have an ErrorOr object. What do you think?
Also, I dont like dynamic and I dont like exceptions 😉
Edit: result.ToErrors() line ToErrors is an extension😀

novalogic
Автор

I have just started to move my API to clean architecture. This helps a lot. Thank you. ❤
Can we have some details about how to work with a SQL database following your approach and how to run CRUD operation in Database?

zadidbinazad
Автор

What status code would you assign to Error.Failure? 500? I guess it depends on what I understand by a failure in my system. I think that NotFound, Conflict and Validation solve the 99% of the usecases. So the Failure could mean some unrecoverable error caused by the server, but the one that you expect to happen eventually. But then what about Unexpected? If you ever return Error.Unexpected in your code, it means that you expect something may happen, so it isn’t unexpected. What is your methodology? And big thanks for the amazing erroror library!

matthewrossee