What?! Zero comments about the most beautiful part of this video?! 😍🐶 28:15
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.
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 👍
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
Thanks for creating awesome stuff. Please keep making videos on c#.
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.
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?
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.
i wish i could be as good as you guys in software development world.
Great video, but where is the promised video where you talk about application and domain layer validation? I really need this! <3
Finally, I'm very happy and great video
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 IEnumerable<IValidator<TRequest>> _validators; public ValidationBehaviour(IEnumerable<IValidator<TRequest>> validators) { _validators = validators; } public async Task<ErrorOr<TResponse>> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<ErrorOr<TResponse>> next) { if (!_validators.Any()) { return await next(); } var context = new ValidationContext<TRequest>(request); var validationResults = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken))); var errors = validationResults.SelectMany(result => 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😀
I really enjoy the series. Have learned a lot from these series. Anyway, alt+z should toggle the words wrap automatically.
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!
All my sympathies to your enter key
Thanks!
Teşekkürler.
the tutorials are really great, thanks a lot
Hey dude love your content. Are you going to do a video on testing the api? Love to see your strategy etc.
@tiagohenrique7685