CQS: Method can either change state or return a value - not both CQRS: Like CQS, but not as strict regarding the return value, the main emphasis is on having a clear boundary between Commands and Queries Mediator Pattern: Promote loose coupling between objects by having them interact via a mediator rather than referencing each other MediatR: An in-memory implementation of the Mediator pattern, where MediatR requests & MediatR handlers are wired up during the DI setup Splitting Logic By Feature: Having each use case in a separate file What we demonstrated today is using the MediatR package to implement the Mediator design pattern. We separated our use cases into different files, and following CQRS, we defined clear boundaries between our Commands and Queries by nesting Command Handlers and Query Handlers in different folders. Please remember that the definitions above follow the original definitions of the people who coined the terms, not interpretations of others over the years. Hope that clears up any confusion 🙂
Thanks for sharing. When can we expect next video 🙂 eagerly waiting... Can you upload videos twice a week please 😀... I know this is too much to ask... This is the best content so far on the TH-cam.... Keep it up....
Update on how you should implement the DI in Mediatr starting version 12.0.0: services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly));
good first steps in the "right" direction, when behaviours will kick in to have logging, transactions, validations, and so on. A long way to go even considering DDD but I'm sure people will enjoy the final result! Just an advice to people who are watching this series (but in general any dev video): after having watched a vid, do your own research on the topic, don't assume what you are actually listened to is good enough or a perfect fit for your needs because things will evolve next episodes and will change a lot of things, also there isn't a silver bullet so it's worth going deeper into the subjects to understand the ins and outs. You'll find yourself changing your approach every now and then: it's a sign you are learning and that's the good thing. The "bad" side is that the learning path never ends :) (actually having to learn everyday is one of the things I like the most about this job and I think every good programmer need to have this approach)
I love the MediatR library. I actually didn’t know you could use just use the ISender instead of the full IMediator to get a slimmed down mediator if that’s all you use if for. Another great VOD in the books!
When I met the MediatR for the first time (at work in one of our projects) I was shocked how beautiful this library (and CQRS pattern of course) is. It makes Controllers so clean and small with no effort. I hope for the 'Notification' part in MediatR 😊
Your video are pure gold! Thank you! I'm switching from Game Dev to Backend development and your videos are helping me a lot. I'm also studying DDD so I can't wait to see more about!
Honest question. But what value CQRS and separating things into commands and queries actually bring? Underneath it's all just MediatR.IRequest - so they are handled exactly the same way by the command bus/Mediator. The handlers ultimatelly don't really differ. Queries, as you said in one of the comments below, can morph into commands, for example when Login Query needs to also update DB with amount of login attempts - it becomes a Command, requiring a refactor which in some cases might be a breaking change. I could see it having some value if it was, I dunno, an interface for repository - where we'd only query data from repository, or update it. But that's usually unrealistic, and Commands/Queries quickly spread into business logic (like here with Login/Create Token requests). Since Commands also return values they are, essentially better Queries anyway. Also can Query Handlers issue Commands and indirectly change values in the store? Or do they need to be refactored into Commands too now? I'm asking all that, because I'm at the tail end of massive refactor, removing CQRS from quite big service, in my company. After few years of development, we realized separating things into Commands and Queries didn't add anything, except for confusion. Queries once created weren't refactored into Commands, if a need arose, Commands sometimes acted like Queries, Queries like Commands, and it all become a massive mess. We tried enforcing restriction, by having dedicated interfaces for Commands/Queries, that restricted what they can return etc. We tried separating business logic into very granular commands/queries, but that become overwhelming - for ex. Authentication - Query for info if user can be authenticated, send Command to update it's attempt number, send query to check if a refresh token is available, if yes, send command to invalidate the token, send command to generate new access/refresh token, send query to get the tokens etc.. This become unwieldly. With so many granular commands/queries it also become increasingly hard to keep track of which are still actually used, as the development progressed.. So now we are throwing it all away, and scaling back the granularity of each MediatR.IRequest. We just have "high level" request send from API endpoint/Controller to a MediatR handler, which handles it, and if it needs more granularity - it sends more requests for other handlers to deal with. That loose coupling that MediatR provides is still there and this is great. But any separation between Commands and Queries is gone.
I was reading the comments precisely for this, I mean if someone thinks that CQRS doesn't add too much value, but unnecessary complexity, and, as you said, queries can evolve into commands depending on the business, and that, for sure, will require a more complex process of refactoring. I'm really enjoying what Amichai is doing with these videos and showing how we can do the same thing. And, for that reason, we can infer what is better to use depending on what we need. PS: Sorry for my English😅
Hi mr:Amichai at 10:05 of the video you miss to say to install the mediatR package in api layer maybe you cat the video during montage. Really really really thanks for your efforts. It's a great series on TH-cam. I hope to talk about Dockers and containers. Thanks again.
When generating a new Auth-Token and saving it in the DB, IMO that does change the State. Login and the Pop method on your Example earlier are pretty much the same thing. Right?
Great video as always. I'm really enjoying the series. Quick question - where should we apply the validation. From your screenshot (at the end of the video) it looks like it should be done in the application. In my opinion we should also validate the request too. Can you please throw some light here ?
I would put it in the application or domain entities depending on the scope of the validation. Validation is one of the core reasons to have a domain in the first place in clean architecture.
Come across your videos recently and they're very good, right content and right pace from my perspective at least. I do have a question regarding the login although this is probably more applicable if the authentication services were self-implemented(which you should never do, of course, instead rely on AzureAD etc.) Something as simple as Login can still have side-effects such as incrementing a failed login count, writing an audit trail, etc. Would these be implemented in the application layer as commands whilst the consumer still regards Login as a read-only activity and is unaware of these commands running?
How easy is to mock the MediatR Send method for unit tests? Im struggling to see the benefits here of using MediatR vs having Interfaces for each CommandHandler and using that. Great series btw! Thanks :)
Same as any other interface 🤓 If you have an interface for all your command handlers you will have to manually wire it up in the DI setup, or do assembly scanning similar to what MediatR does out of the box
@Amichai thanks very much for this EXCELLENT Tutorial. Just a little bit too fast moving code around. Maybe I hope you don't mind publishing the source code so that one can read it offline to see what is going on?. Many thanks❤
That's great and what we have done, but plus that i'd rather to split persistence layer from application layer. So that the logic and db operations would be separated. 👍
Hey, always waiting for your next video! :) How did you do the replacement in 5:55? -> Answer is the "Vim Emulator" Extension with the command seen at the blue bottom bar And who can there be a base construct in 11:47?
I didn't get your magic tricks when you install Mediator into the Application project and adding Mediator library from Api project. But Api doesn't have installed mediator library. Or the whole job do Git Compiler?
I think it is a stretch, calling a "Login" method a query. Depending on your underlying implementation, it MIGHT write to the persistence store. Ie, if you're not using bearer tokens, but actually storing the login i a database. The name Login, is imperative form, and suggests it is a command, regardless of the underlying implementation. IMO "login" _does_ change state not matter what - maybe not in the database, but conceptually the systems state is changed when invoked, since the user is logged in (which he wasnt before), and that to me, is the definition of a state-change (hence its a command) - not nessecarily a write to a persistence store, since that might change over time and is an infrastructure concern, not application concern
Hello sir, thank you for this great video again. I have a question regarding layers. I see that you create a LoginRequest class and then map it to a LoginQuery by using constructor. Let's suppose we have an incoming request body with at least 20 properties; how would you handle these in controller actions? By manually mapping the fields or is there anything I am missing? Thank you again!
What Tools are you using for it to predict the code? Sometimes time the entire class..
ปีที่แล้ว +3
In .Net Core 7 with version 12 of MediatR on file BuberDinner.Application.DepencyInjection: services.AddMediatR(x => x.RegisterServicesFromAssemblies(typeof(DependencyInjection).Assembly));
I would say, in many cases, yes. We can easily separate logic using Minimal API and inject into every single endpoint different services. Usually MediatR is used in controllers because the last one can have many dependencies but not every endpoint needs them. MediatR allow us to avoid this situation and get less cohesive code. With Minimal API we can reach the same goal without any overhead and additional code. Some people are used to use MediatR and still use it whenever it is possible. Sometimes they as if they refuse to understand that it does more harm than good.
We are using CQRS and IMediatR. In cases where a multiple query/commands must reuse same piece of code, is it ok to call another query/command inside query/command handler or the same code should be extracted to a service and injected in the handler?
Hi I'm getting error at line: in .NET 6 Program.cs file builder.Services.AddMediatR(typeof(Program)); Error: CS1503 Argument 2: cannot convert from 'System.Type' to 'System.Action'
CQRS said that you need to separate Command and Query to database, but in the Register you still need to Query to check user email exists or not. Can you explain is it right when apply CQRS or not
Is there a reason you don't use the Query and/or Command as the action parameter? That's pretty common in other templates and examples that uses these patterns.
Even though it saves the mapping in the controller - Yes, a few reasons: 1. In MS (and I'm sure other companies as well), it's common to publish the contracts project as a NuGet package. Then, clients written in .NET can consume it instead of redefining the same models. It also plays well with versioning, where you would simply consume the new version. 2. Commands/Queries aren't always an exact map of the request. A simple example for this is a PUT endpoint, where the id comes from the route. The command would have both details from the request body and the id from the route. 3. It decouples our use cases from the API definition. Want to change names/add properties to a command or query? No problem 🤓 Does that make sense?
What benefit we get of duplicating a request and then same props in command or query. Why can't we just use command or query directly as param to Api. ?. This will save some boilerplate code. like LoginRequest and LoginQuery will have same props according to this video.
Congratulations on the article Amichai. Let me ask you a question. You don't think using mediatr for the query stack is creating overengineering. Since one of the ideas of CQRS is also to speed up and simplify queries, by using all mediatR objects we are not creating unnecessary objects and instantiating classes that also have a cost. And classes without arguments is quite common, it's just being used to orchestrate to the right handler. Shouldn't we just go straight to the data source? sometimes I get the idea that we create a lot of unnecessary objects for queries.
Great video again :) I like this ideo of splitting by feature. Would you reintroduce a service class again to handle common functionality between different endpoints? And I haven't really understood what the benefit of splitting the contracts project from the api project is. Can anybody shed some light on that?
it's just preference for him I guess. If you are fan of multiple classes in one file, you can put each of these classes from /Contracts in the files where the controllers that use them are defined, so you have everything you need in one file. If one really decides to organize by feature (vertical slices) and not technical concerns (horizontal layers), having everything you need for a feature in one place might be the handiest approach: controller, request, response, handler, validator etc. You can even have the UI that is related to that feature in the same folder :)
Awesome explanation and content. If a part of the code that is defined in a Handler has to be used in another Handler, what should be done? Create a service and encapsulate that functionality so as not to repeat code?
Depending on the duplication you encounter that might mean that 1) you got your logical boundaries wrong or 2) you indeed have to extract that functionality to separate service/domain service/domain entity.
One question Amichai: If we also want to update the user's last login DateTime after each login, our login is still a query or a command? How do you separate these two functionalities?
In the past I've used the Command Pattern as described in the GoF book to facilitate Undo/Redo in MVVM applications by keeping a list of all the command objects. If I was building a web app where I wanted a Rest API and Blazor App for different Presentation layers, would there be any relationship between the GoF commands and the CQRS commands? Could CQRS help with Undo/Redo?
You can use both. The handlers can use your repository interfaces that are implemented in your infra layer. So, it's not an either/or, they are sort of different concerns.
Hi, I love the MediatR but I have a problem with it. We can say that the MediatR handler replace our Services Layer. What happens when a service needs to call another services? Jimmy Bogard discourage calling a Mediatr Request from another Request. what is the solution to this problem? reintroduce a service? Thanks for your help
I assume that if for example registerCommand & loginRequest both required some common functionality, that you would create something like an authenticationService again and use that in the requestHandler. Just my best guess though.
@@richardhaughton9633 Mhh, imo it wouldn't become a 'god' class again because it contains only methods that you need to lift out of any single requestHandler for re-use. Similar to how both requestHandlers use the tokenGenerator.
@@TheFeljoy For example let's say I have a CreateEntityRequestHandler that Handles a CreateEntityRequest. Let's also assume that I have an ImportRequestHandler that handles an ImportRequest. When the ImportRequest detects a new Entity it needs to create it. Should I call the CreateEntityRequest and Send it through the MediatR from the ImportRequestHandler?
@@richardhaughton9633 No. You could create a new class, say a repository class that handles the creation of entities in the system.. now you can just inject that class to your CreateEntityHandler and ImportHandler classes so that you could reuse the logic in multiple handlers..
Hi Amichai, while using CQRS pattern, shall we need to create class for every query? for Ex: Domain Entity ( Order ) I need queries like GetCustomerOrders / GetPaidOrders / GetCanceledOrders / GetOrdersPaidByCreditCard and also complex queries using Store Procedures(for KPIS / Reports ) So for every query / Stored procedure, we need to create separate Class ??
Hello as usual, very nice video, but there something I don't understand. At 9:30 you install MediatR package to the application layer. But just after you use IMediator in a controller (from Api project) how is it possibe? do I missed something. Because in my environment if I want to use a library un a controller, I need to install this library in api project.
Thanks. In clean arch, outer layers have a dependency only on inner layers. Since the presentation layer references the application layer then it's available.
I have an issue with vscode, I don't seem to have the option to "Change namespace to match folder structure" and it is really annoying. Do you know is there a fix for it ? Btw, great searies I really enjoy it and learn a lot, actualy you have inspired me to switch to vscode 👍
People understand mediator as a CQRS pattern, i totally disagree with that. ISender interface wraps Command pattern and it is not about CQRS. It is about request handling per use case,(clean architecture stuff..) IPublisher interface is for in-memory message handling. Normally CQRS is about persistence layer. But, for domain centric projects(you can use DDD) sometimes you need different components for handling that. Every state change on domain could raise a domain event. For that reason, we can use CQRS. It could feed other domains or own query db with that. Also, i think login is a special case and it is not a query. It can generate(also needs HttpPost) a token for that given user. Normally, it is not changing any data on persistence layer but you could persist some columns like last_login_date or device info when business needs. When you login a user, you keep him/her in play. So, user with role is in play for a limited time. When you refresh this token, you gave extra time for that user. For jwt, we don't persist to db, it is in memory. But, also that token contains changed user states which is an authentication result.
Perhaps I could have been clearer regarding the different patterns we used. I've summed up the details the pinned message 🙂 Regarding login being a command or query, I agree it can definitely be a command as well. I prefer defining flows as queries if they don't change any state, but like everything, it depends on the implementation and person taste. What do you think?
great tutorial, but due to such elaborate classes and structures, people hate java/c# and are preferring much simple golang, which also provides better GC than java.
I've been thinking lately about Azure functions vs web apis. Cost of Azure functions are pretty low comparing to web apis (up to a certain volume of triggers/queues). Web api requires an app service which has an uptime up to 93 - 98%% according to azure datacenters. If its cheaper and you can easy achieve seperation of concerns? Does anyone one know why and when you want to choose the one over the other?
From the projects I came across, most became really hard to navigate once the shared "building blocks" become generic to support the various modules. Perhaps for devs who are aligned on the architecture it can be super convenient, but it can definitely add another layer of complexity above a single project similar to the one we are building which already can be tough to onboard. Does that make sense?
Thank you so much for the videos, I love them, however, it fails to highlight one key aspect which is, you failed to make us beginners understand what problem the MediatR nuget package is trying to solve or why we should even use it. I think explaining the problem the package solves would help us appreciate it and know when to use it and even come up with other impelementations. Again, thank you for your videos and I love them.
I don't understand. What happened to old-fashioned Interface extraction of the data for the ViewModel Why am I adding a stupid library for extra download for no good reason? You can create a ViewModel Folder and each entity, create a folder for itself, and create the interface for it. CQRS, something, Create a folder under the same repository and call one of them Transactions or whatever you want to call it to make it clear, and the other one Query. let your services call it accordingly. Make it clear. You don't need all these things and make your code bigger and bigger by adding unnecessary libraries.
And, you don't need any mapping software as well. What is going on? Why are we adding these libraries where you can do it yourselves easily and your project size will be smaller? Are we trying to accommodate not-so-good programmers? Is that why we are having too many hacks?
I really appreciate your videos and the way you explain everything, but... I'm struggling to finish your videos when that "yeeeeessssss" is repeated all the time.
Why are you separating command and query outside of IAuthenticationService? No code outside of the implementation cares. You're introducing something and a LOT of code that doesn't matter. The implementation of authentication's repository (maybe IAuthenticationRepository) might care because there is a read side and a write/transaction side, but not at the front end or what should be a very thin, single line, of code in the controller. Oh, and what happens if login requires a counter update to restrict failures every n minutes? Also, even query commands will/might update the log database, but I guess that doesn't count. Sorry for the rant.
This goes so fast that it's annoying. Indeed, you know how to do it well, but please go slower, especially on the shortcuts, the contextual menus, and the change of files. You'll become a great YT teacher. Good work!
I'll keep this in mind for the future videos, thanks for the feedback. I'm thinking of specifying the difficulty level in the beginning of the video so viewers can adjust the playback speed accordingly.
Cool. I have been working with CQRS and MediatR a lot and it's hella clean and works very well with FluentValidation, other/custom middlewares, integration tests and in general with DDD. I've been only wondering why would you register MediatR (or before, without MediatR, your services) in a separate DependencyInjection class and call it in Startup.cs/Program.cs instead of just calling AddMediatR() directly in Program.cs/Startup.cs? Your API layer needs to reference Application, anyway, so what's the point? To keep Application dependencies setup code in Application layer? Wouldn't it be cleaner to create a private method in Program.cs/Startup.cs directly e.g. RegisterApplicationDependencies(serviceCollection) and keep all the setup in one place? I've already seen people going the extension class way and then registering the same thing twice in two different classes, in two different ways, once in Startup.cs directly then in an extension method again because they couldn't keep track on where everything is registered when it's so split, especially developers who didn't write that particular piece of code. What's the gain here?
CQS: Method can either change state or return a value - not both
CQRS: Like CQS, but not as strict regarding the return value, the main emphasis is on having a clear boundary between Commands and Queries
Mediator Pattern: Promote loose coupling between objects by having them interact via a mediator rather than referencing each other
MediatR: An in-memory implementation of the Mediator pattern, where MediatR requests & MediatR handlers are wired up during the DI setup
Splitting Logic By Feature: Having each use case in a separate file
What we demonstrated today is using the MediatR package to implement the Mediator design pattern. We separated our use cases into different files, and following CQRS, we defined clear boundaries between our Commands and Queries by nesting Command Handlers and Query Handlers in different folders.
Please remember that the definitions above follow the original definitions of the people who coined the terms, not interpretations of others over the years.
Hope that clears up any confusion 🙂
Thanks for sharing. When can we expect next video 🙂 eagerly waiting... Can you upload videos twice a week please 😀... I know this is too much to ask... This is the best content so far on the TH-cam.... Keep it up....
12:56 isn't it better to return ValueTask.FromResult() if it is async now?
Update on how you should implement the DI in Mediatr starting version 12.0.0:
services.AddMediatR(config => config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly));
Thank you!
Thanks!
You are a savior THANK YOU
Thanks!
Hands down best explanation of CQRS I have found with non-trivial practical example to understand how it is implemented. Thank you!
good first steps in the "right" direction, when behaviours will kick in to have logging, transactions, validations, and so on.
A long way to go even considering DDD but I'm sure people will enjoy the final result!
Just an advice to people who are watching this series (but in general any dev video): after having watched a vid, do your own research on the topic, don't assume what you are actually listened to is good enough or a perfect fit for your needs because things will evolve next episodes and will change a lot of things, also there isn't a silver bullet so it's worth going deeper into the subjects to understand the ins and outs. You'll find yourself changing your approach every now and then: it's a sign you are learning and that's the good thing. The "bad" side is that the learning path never ends :) (actually having to learn everyday is one of the things I like the most about this job and I think every good programmer need to have this approach)
This is the way! 🛣🛣🛣
I've watched many many people online but you are foremost the best one!
I love the MediatR library. I actually didn’t know you could use just use the ISender instead of the full IMediator to get a slimmed down mediator if that’s all you use if for. Another great VOD in the books!
Me too. Glad to know.
There's no doubt that the series is great, but the comments and answers are also valuable as I learn from them.
When I met the MediatR for the first time (at work in one of our projects) I was shocked how beautiful this library (and CQRS pattern of course) is. It makes Controllers so clean and small with no effort.
I hope for the 'Notification' part in MediatR 😊
I'm following this course using .Net 8, so far so good. This was an enlightening section, thanks for putting it together.
I need more! This series is fantastic, cant get episodes fast enough :D
Amichal - great video as usual. Great, concise and comprehensible info.
The pacing is amazing for people like me who are impatient lol, seriously these videos are wonderful.
Haha I'm super impatient myself, which is why I like a higher pace. I'm starting to think it might be just a little too fast 👀
I am already loving this series
Your video are pure gold! Thank you! I'm switching from Game Dev to Backend development and your videos are helping me a lot. I'm also studying DDD so I can't wait to see more about!
Awesome to hear. Thanks, Gaetano!
Your trainings are great, thank you very much, we would be glad if you support these lessons with real real database.
We'll use EF Core with SQL in the final result 🤙🏼
@@amantinband thank you so much, you are great
Another amazing video, can't wait for the next one :D
Honest question. But what value CQRS and separating things into commands and queries actually bring? Underneath it's all just MediatR.IRequest - so they are handled exactly the same way by the command bus/Mediator. The handlers ultimatelly don't really differ. Queries, as you said in one of the comments below, can morph into commands, for example when Login Query needs to also update DB with amount of login attempts - it becomes a Command, requiring a refactor which in some cases might be a breaking change.
I could see it having some value if it was, I dunno, an interface for repository - where we'd only query data from repository, or update it. But that's usually unrealistic, and Commands/Queries quickly spread into business logic (like here with Login/Create Token requests).
Since Commands also return values they are, essentially better Queries anyway.
Also can Query Handlers issue Commands and indirectly change values in the store? Or do they need to be refactored into Commands too now?
I'm asking all that, because I'm at the tail end of massive refactor, removing CQRS from quite big service, in my company. After few years of development, we realized separating things into Commands and Queries didn't add anything, except for confusion. Queries once created weren't refactored into Commands, if a need arose, Commands sometimes acted like Queries, Queries like Commands, and it all become a massive mess. We tried enforcing restriction, by having dedicated interfaces for Commands/Queries, that restricted what they can return etc. We tried separating business logic into very granular commands/queries, but that become overwhelming - for ex. Authentication - Query for info if user can be authenticated, send Command to update it's attempt number, send query to check if a refresh token is available, if yes, send command to invalidate the token, send command to generate new access/refresh token, send query to get the tokens etc.. This become unwieldly. With so many granular commands/queries it also become increasingly hard to keep track of which are still actually used, as the development progressed..
So now we are throwing it all away, and scaling back the granularity of each MediatR.IRequest. We just have "high level" request send from API endpoint/Controller to a MediatR handler, which handles it, and if it needs more granularity - it sends more requests for other handlers to deal with. That loose coupling that MediatR provides is still there and this is great. But any separation between Commands and Queries is gone.
I was reading the comments precisely for this, I mean if someone thinks that CQRS doesn't add too much value, but unnecessary complexity, and, as you said, queries can evolve into commands depending on the business, and that, for sure, will require a more complex process of refactoring.
I'm really enjoying what Amichai is doing with these videos and showing how we can do the same thing. And, for that reason, we can infer what is better to use depending on what we need.
PS: Sorry for my English😅
Thanks, this how I've been implementing my apps. So much clearer to reason about the code base.
Good job as always. I can`t wait for your upcoming videos.
Just found this series this week. Very interesting and informative. Much thanks for creating this series and keep up the good work!
Hi mr:Amichai at 10:05 of the video you miss to say to install the mediatR package in api layer maybe you cat the video during montage.
Really really really thanks for your efforts. It's a great series on TH-cam. I hope to talk about Dockers and containers.
Thanks again.
As far as I remember Pascal language had basic segregation to procedures(doesn't return value) and functions(returns value)
Awesome video . Waiting for other parts for DD and cqrs
When generating a new Auth-Token and saving it in the DB, IMO that does change the State.
Login and the Pop method on your Example earlier are pretty much the same thing. Right?
Great video as always. I'm really enjoying the series. Quick question - where should we apply the validation. From your screenshot (at the end of the video) it looks like it should be done in the application. In my opinion we should also validate the request too. Can you please throw some light here ?
Yes, in the application - in the handler for the operation to be exact.
I would put it in the application or domain entities depending on the scope of the validation. Validation is one of the core reasons to have a domain in the first place in clean architecture.
@@sunefred I'm new to clean architecture, thanks for clarifying my doubt.
Love your videos
I am in love with your content, wait for the next videos eagerly, when are u coming up with next videos?
Come across your videos recently and they're very good, right content and right pace from my perspective at least.
I do have a question regarding the login although this is probably more applicable if the authentication services were self-implemented(which you should never do, of course, instead rely on AzureAD etc.) Something as simple as Login can still have side-effects such as incrementing a failed login count, writing an audit trail, etc. Would these be implemented in the application layer as commands whilst the consumer still regards Login as a read-only activity and is unaware of these commands running?
please make videos on testing, CI/CD. your explanations are awesome 👍❤
Follow him with playback speed 0.75😊
I really appreciate your content man!
than you very much!
How easy is to mock the MediatR Send method for unit tests?
Im struggling to see the benefits here of using MediatR vs having Interfaces for each CommandHandler and using that.
Great series btw! Thanks :)
Same as any other interface 🤓 If you have an interface for all your command handlers you will have to manually wire it up in the DI setup, or do assembly scanning similar to what MediatR does out of the box
Should the "Handle" methods in the "RegisterCommand Handler" and "RegisterQueryHandler" classes be asynchronous?
Great video! Will we have a deep dive into the authentication and authorization flow with JWT and OAuth?
We'll cover it but not sure yet if it will be a deep dive as part of this series
How would you keep the clean architecture and CQRS structure but not load whole aggregates if not needed like you mentioned at the end?
@Amichai thanks very much for this EXCELLENT Tutorial. Just a little bit too fast moving code around. Maybe I hope you don't mind publishing the source code so that one can read it offline to see what is going on?. Many thanks❤
That's great and what we have done, but plus that i'd rather to split persistence layer from application layer. So that the logic and db operations would be separated. 👍
It is. Persistence is in the Infrastructure layer, not the application layer. Or perhaps you are seeing something I missed?
I'm really fascinated by the shortcuts that you're using! Is it really the art of vs code extensions and keymaps or you've just cut the video??
Hey, always waiting for your next video! :)
How did you do the replacement in 5:55?
-> Answer is the "Vim Emulator" Extension with the command seen at the blue bottom bar
And who can there be a base construct in 11:47?
Yup regarding vim, not sure what you mean in 11:47
This is so cool, I cannot wait for next one :P
at 9:50 why do you add the MediatR deps only to Application app and not also to Api?
I didn't get your magic tricks when you install Mediator into the Application project and adding Mediator library from Api project. But Api doesn't have installed mediator library. Or the whole job do Git Compiler?
I think it is a stretch, calling a "Login" method a query. Depending on your underlying implementation, it MIGHT write to the persistence store. Ie, if you're not using bearer tokens, but actually storing the login i a database. The name Login, is imperative form, and suggests it is a command, regardless of the underlying implementation.
IMO "login" _does_ change state not matter what - maybe not in the database, but conceptually the systems state is changed when invoked, since the user is logged in (which he wasnt before), and that to me, is the definition of a state-change (hence its a command) - not nessecarily a write to a persistence store, since that might change over time and is an infrastructure concern, not application concern
Hello sir, thank you for this great video again.
I have a question regarding layers. I see that you create a LoginRequest class and then map it to a LoginQuery by using constructor. Let's suppose we have an incoming request body with at least 20 properties; how would you handle these in controller actions? By manually mapping the fields or is there anything I am missing?
Thank you again!
Maybe he should've changed the type of the argument of the Login action method to just LoginQuery and scrapped LoginRequest.
He is going to use AutoMapper in the future I think he mentioned in the first part. I might be wrong tho.
@@hero3616 he is going to use Mapster
Yup, we'll use Mapster
Is there any argument against using the LoginQuery as Controller request?
What Tools are you using for it to predict the code? Sometimes time the entire class..
In .Net Core 7 with version 12 of MediatR on file BuberDinner.Application.DepencyInjection:
services.AddMediatR(x => x.RegisterServicesFromAssemblies(typeof(DependencyInjection).Assembly));
Thank you!
Any plan to extend the series to make them Microservice with API gateway?
since we now have aspnet minimal APIs, is MediatR redundant?
I would say, in many cases, yes. We can easily separate logic using Minimal API and inject into every single endpoint different services. Usually MediatR is used in controllers because the last one can have many dependencies but not every endpoint needs them. MediatR allow us to avoid this situation and get less cohesive code. With Minimal API we can reach the same goal without any overhead and additional code.
Some people are used to use MediatR and still use it whenever it is possible. Sometimes they as if they refuse to understand that it does more harm than good.
i’m new to .net in VS code what is your extension for VS code to help you . thanks
Great video! Do you mind showing in one of the next videos maybe additional integration with DB with dapper for reading and EF for write?
Hello. Which software do you sue to create these arrows and shapes on the screen? Thanks !
ZoomIt
We are using CQRS and IMediatR. In cases where a multiple query/commands must reuse same piece of code, is it ok to call another query/command inside query/command handler or the same code should be extracted to a service and injected in the handler?
Hi I'm getting error at line: in .NET 6 Program.cs file
builder.Services.AddMediatR(typeof(Program));
Error:
CS1503 Argument 2: cannot convert from 'System.Type' to 'System.Action'
Nice Video. Thanks!. Could you please elaborate why we do need to generate the JWT token during registration process ?
You don't necessarily need to do it.
CQRS said that you need to separate Command and Query to database, but in the Register you still need to Query to check user email exists or not. Can you explain is it right when apply CQRS or not
What software do you use to create the system architecture diagrams? Really like the way it looks
i think it just figma; edit: sorry for after 1 year :D
Is there a reason you don't use the Query and/or Command as the action parameter? That's pretty common in other templates and examples that uses these patterns.
Even though it saves the mapping in the controller - Yes, a few reasons:
1. In MS (and I'm sure other companies as well), it's common to publish the contracts project as a NuGet package. Then, clients written in .NET can consume it instead of redefining the same models. It also plays well with versioning, where you would simply consume the new version.
2. Commands/Queries aren't always an exact map of the request. A simple example for this is a PUT endpoint, where the id comes from the route. The command would have both details from the request body and the id from the route.
3. It decouples our use cases from the API definition. Want to change names/add properties to a command or query? No problem 🤓
Does that make sense?
BTW, what tool are you using for the pointer, frames, and arrows? I think it's cool.
ZoomIt
you are creating a new token in the login method; doesnt it make it a command?
anyway love your vids, thanks
at 11:10 you are extending a Record not define a return value... am i wrong?
Isnt the model in API and the command reduandant?
What benefit we get of duplicating a request and then same props in command or query. Why can't we just use command or query directly as param to Api. ?. This will save some boilerplate code.
like LoginRequest and LoginQuery will have same props according to this video.
Amazing video - Many thanks
Best way to return errors is exceptions!
Which tool do you use to draw on the screen?
Congratulations on the article Amichai.
Let me ask you a question.
You don't think using mediatr for the query stack is creating overengineering.
Since one of the ideas of CQRS is also to speed up and simplify queries, by using all mediatR objects we are not creating unnecessary objects and instantiating classes that also have a cost.
And classes without arguments is quite common, it's just being used to orchestrate to the right handler. Shouldn't we just go straight to the data source? sometimes I get the idea that we create a lot of unnecessary objects for queries.
Awesome tutorial ♥️
Thanks for the video and the series.
May I ask what tool do you use to create diagram of the application, like in 8:18
It's GitHub Co-Pilot :)
Great video again :) I like this ideo of splitting by feature. Would you reintroduce a service class again to handle common functionality between different endpoints? And I haven't really understood what the benefit of splitting the contracts project from the api project is. Can anybody shed some light on that?
it's just preference for him I guess. If you are fan of multiple classes in one file, you can put each of these classes from /Contracts in the files where the controllers that use them are defined, so you have everything you need in one file.
If one really decides to organize by feature (vertical slices) and not technical concerns (horizontal layers), having everything you need for a feature in one place might be the handiest approach: controller, request, response, handler, validator etc. You can even have the UI that is related to that feature in the same folder :)
Awesome explanation and content. If a part of the code that is defined in a Handler has to be used in another Handler, what should be done? Create a service and encapsulate that functionality so as not to repeat code?
Depending on the duplication you encounter that might mean that 1) you got your logical boundaries wrong or 2) you indeed have to extract that functionality to separate service/domain service/domain entity.
It depends. What code? Perhaps you need to create some domain events? Keep the SOLID principles in mind.
One question Amichai:
If we also want to update the user's last login DateTime after each login, our login is still a query or a command? How do you separate these two functionalities?
It would then be command 👍🏼
In the past I've used the Command Pattern as described in the GoF book to facilitate Undo/Redo in MVVM applications by keeping a list of all the command objects.
If I was building a web app where I wanted a Rest API and Blazor App for different Presentation layers, would there be any relationship between the GoF commands and the CQRS commands? Could CQRS help with Undo/Redo?
So far, I don't know which is the best case to use the cqrs pattern or the repository pattern.
You can use both. The handlers can use your repository interfaces that are implemented in your infra layer. So, it's not an either/or, they are sort of different concerns.
@@pilotboba Thank You!
Do you have a list of the extensions you use in VsCode? I would love to see if some of them are available in VS as they look super useful!
Yeah I have a video all about vscode for .NET: th-cam.com/video/m9HvsB1-hAo/w-d-xo.html
Hi, I love the MediatR but I have a problem with it. We can say that the MediatR handler replace our Services Layer. What happens when a service needs to call another services? Jimmy Bogard discourage calling a Mediatr Request from another Request. what is the solution to this problem? reintroduce a service? Thanks for your help
I assume that if for example registerCommand & loginRequest both required some common functionality, that you would create something like an authenticationService again and use that in the requestHandler. Just my best guess though.
@@TheFeljoy Yes that's what I thought but we are then back to the god Service class.
@@richardhaughton9633 Mhh, imo it wouldn't become a 'god' class again because it contains only methods that you need to lift out of any single requestHandler for re-use. Similar to how both requestHandlers use the tokenGenerator.
@@TheFeljoy For example let's say I have a CreateEntityRequestHandler that Handles a CreateEntityRequest. Let's also assume that I have an ImportRequestHandler that handles an ImportRequest. When the ImportRequest detects a new Entity it needs to create it. Should I call the CreateEntityRequest and Send it through the MediatR from the ImportRequestHandler?
@@richardhaughton9633 No. You could create a new class, say a repository class that handles the creation of entities in the system.. now you can just inject that class to your CreateEntityHandler and ImportHandler classes so that you could reuse the logic in multiple handlers..
Hi Amichai, while using CQRS pattern, shall we need to create class for every query?
for Ex: Domain Entity ( Order )
I need queries like GetCustomerOrders / GetPaidOrders / GetCanceledOrders / GetOrdersPaidByCreditCard and also complex queries using Store Procedures(for KPIS / Reports )
So for every query / Stored procedure, we need to create separate Class ??
Yes, if you will follow that approach you'll respect the S in SOLID principle.
Hello as usual, very nice video, but there something I don't understand. At 9:30 you install MediatR package to the application layer. But just after you use IMediator in a controller (from Api project) how is it possibe? do I missed something. Because in my environment if I want to use a library un a controller, I need to install this library in api project.
Thanks. In clean arch, outer layers have a dependency only on inner layers. Since the presentation layer references the application layer then it's available.
@@amantinband Ok thanks for the quick answer ;-)
One suggestion. Add a link in your repos to the youtube videos.
That's a good idea. I hope to get around to it :)
I have an issue with vscode, I don't seem to have the option to "Change namespace to match folder structure" and it is really annoying. Do you know is there a fix for it ?
Btw, great searies I really enjoy it and learn a lot, actualy you have inspired me to switch to vscode 👍
People understand mediator as a CQRS pattern, i totally disagree with that. ISender interface wraps Command pattern and it is not about CQRS. It is about request handling per use case,(clean architecture stuff..) IPublisher interface is for in-memory message handling. Normally CQRS is about persistence layer. But, for domain centric projects(you can use DDD) sometimes you need different components for handling that. Every state change on domain could raise a domain event. For that reason, we can use CQRS. It could feed other domains or own query db with that.
Also, i think login is a special case and it is not a query. It can generate(also needs HttpPost) a token for that given user. Normally, it is not changing any data on persistence layer but you could persist some columns like last_login_date or device info when business needs. When you login a user, you keep him/her in play. So, user with role is in play for a limited time. When you refresh this token, you gave extra time for that user. For jwt, we don't persist to db, it is in memory. But, also that token contains changed user states which is an authentication result.
Perhaps I could have been clearer regarding the different patterns we used. I've summed up the details the pinned message 🙂
Regarding login being a command or query, I agree it can definitely be a command as well. I prefer defining flows as queries if they don't change any state, but like everything, it depends on the implementation and person taste. What do you think?
great tutorial, but due to such elaborate classes and structures, people hate java/c# and are preferring much simple golang, which also provides better GC than java.
I've been thinking lately about Azure functions vs web apis. Cost of Azure functions are pretty low comparing to web apis (up to a certain volume of triggers/queues).
Web api requires an app service which has an uptime up to 93 - 98%% according to azure datacenters.
If its cheaper and you can easy achieve seperation of concerns?
Does anyone one know why and when you want to choose the one over the other?
Do you think that using modular monolith with ddd is good approach?
From the projects I came across, most became really hard to navigate once the shared "building blocks" become generic to support the various modules. Perhaps for devs who are aligned on the architecture it can be super convenient, but it can definitely add another layer of complexity above a single project similar to the one we are building which already can be tough to onboard. Does that make sense?
Great Video
Thank you
what software that you use in the video, to spawn box and arrow?
ZoomIt
@@amantinband okay thank you very much, I like to watch your tutorial video
Awesome
Thank you so much for the videos, I love them, however, it fails to highlight one key aspect which is, you failed to make us beginners understand what problem the MediatR nuget package is trying to solve or why we should even use it. I think explaining the problem the package solves would help us appreciate it and know when to use it and even come up with other impelementations. Again, thank you for your videos and I love them.
ErrorOr I wish you can share its code
I just happen to have a video about it 😉
th-cam.com/video/tZ8gGqiq_IU/w-d-xo.html
I don't understand. What happened to old-fashioned Interface extraction of the data for the ViewModel
Why am I adding a stupid library for extra download for no good reason?
You can create a ViewModel Folder and each entity, create a folder for itself, and create the interface for it.
CQRS, something, Create a folder under the same repository and call one of them Transactions or whatever you want to call it to make it clear, and the other one Query. let your services call it accordingly. Make it clear. You don't need all these things and make your code bigger and bigger by adding unnecessary libraries.
And, you don't need any mapping software as well. What is going on? Why are we adding these libraries where you can do it yourselves easily and your project size will be smaller? Are we trying to accommodate not-so-good programmers? Is that why we are having too many hacks?
Wait did I get click baited on Twitter? Where is the controversy
👀
This one is not useful in my use case, we build too small API that I prefer the god class than using Mediator.
I really appreciate your videos and the way you explain everything, but... I'm struggling to finish your videos when that "yeeeeessssss" is repeated all the time.
Why are you separating command and query outside of IAuthenticationService? No code outside of the implementation cares. You're introducing something and a LOT of code that doesn't matter. The implementation of authentication's repository (maybe IAuthenticationRepository) might care because there is a read side and a write/transaction side, but not at the front end or what should be a very thin, single line, of code in the controller. Oh, and what happens if login requires a counter update to restrict failures every n minutes? Also, even query commands will/might update the log database, but I guess that doesn't count. Sorry for the rant.
This goes so fast that it's annoying. Indeed, you know how to do it well, but please go slower, especially on the shortcuts, the contextual menus, and the change of files. You'll become a great YT teacher. Good work!
I'll keep this in mind for the future videos, thanks for the feedback. I'm thinking of specifying the difficulty level in the beginning of the video so viewers can adjust the playback speed accordingly.
This is rather CQS, not CQRS. All you did just separated classes.
1:45, 2:27 😉
MediatR sucks. So does AutoMapper. Don't use them.
Cool. I have been working with CQRS and MediatR a lot and it's hella clean and works very well with FluentValidation, other/custom middlewares, integration tests and in general with DDD.
I've been only wondering why would you register MediatR (or before, without MediatR, your services) in a separate DependencyInjection class and call it in Startup.cs/Program.cs instead of just calling AddMediatR() directly in Program.cs/Startup.cs? Your API layer needs to reference Application, anyway, so what's the point? To keep Application dependencies setup code in Application layer? Wouldn't it be cleaner to create a private method in Program.cs/Startup.cs directly e.g. RegisterApplicationDependencies(serviceCollection) and keep all the setup in one place? I've already seen people going the extension class way and then registering the same thing twice in two different classes, in two different ways, once in Startup.cs directly then in an extension method again because they couldn't keep track on where everything is registered when it's so split, especially developers who didn't write that particular piece of code. What's the gain here?