This is a sample implementation of ASP.NET MVC4, MongoDB and Ninject to act as a starting template if you are going to use these technologies in your project with a CQRS pattern.
Audience
If most of these terms look unfamiliar then this post is probably not for you: CQRS, Repository, Aggregate (of DDD), NuGet, Unit Testing, Dependency Injection, Document DB. Due to the scope of this post, I won’t be able to go in details in any of these topics as this is a direct implementation.
Greg Young did a few paragraphs intro on CQRS here: CQRS, Task Based UIs, Event Sourcing agh, if you want a simple intro I recommend at least reading the first half of Greg’s post (before the Event Sourcing).
Scope and Definition
In this post, I mean the plain-CQRS pattern and not the whole patterns that are associated with CQRS. Plain CQRS opens the door for other patterns such as Event Sourcing and ES is usually associated with CQRS. This is the plain CQRS with no other associated pattern.
Choice of Technology
I chose MongoDB due to its open licence policy and simplicity, Ninject due to its licence, simplicity and Ninject.Extensions.Conventions
extension that makes my code DRYer.
I could have chosen SQL Server, but for simplicity reasons and to get the idea across, Document DBs are easier to work with. You could also tweak this sample implementation to work on an RDBMS as long as you get the repository right.
This is a sample implementation of ASP.NET MVC4, MongoDB and Ninject to act as a starting template, in case you are going to use these technologies in your project with a CQRS pattern.
Task Application
This is meant to be a trivial application, so that the focus is shifted from the features to the MVC with CQRS pattern. The application:
- Enables querying the tasks. When the user clicks “Query”, if the Completed is selected, it will display completed tasks and if it is not selected, it will display uncompleted tasks. This is meant to represent the start of a CQRS’s Query.
- Checking or unchecking any checkbox in the “Completed?” column will update the task, via Ajax. This is meant to represent the start of a CQRS’s Command.
- Has no way to add or delete tasks. To load sample tasks into the DB, I have included, in the download, a MongoDB script that will populate the DB.
Why using CQRS with MVC?
I recently wrote You should unit test your controller, NOT!, where I gave guidelines that an MVC controller should have almost no code, so it doesn’t even require unit testing, but it is really difficult to show how to achieve this within the scope of that post.
Using CQRS enforces better separation of concerns and produces an almost-empty controller, where the viewmodel turns to a query, when getting data or turns into a command, when posting data.
The diagram above is a sketch of the implementation of the solution, it will get clearer when you progress through the post and read the source code.
Solution Structure
First, whenever, you notice the use of “AT” in the namespace, you can replace that with your company name, as you’ve already concluded, ehmm, AT are my initials.
The solution is using VS 2012 and has 4 projects:
AT.Core
: This is where the infrastructure classes are, such as the CQRS infrastructure classes. AT.SampleApp.Cqrs
: Commands, command handlers, queries, query handlers, query results and domain classes. This is where your business logic is. This project references AT.Core
. In this sample project it has one sample query TasksByStatusQuery
and one command ChangeTaskStatusCommand
. AT.SampleApp.Cqrs.Test.Unit
: Unit tests for the AT.SampleApp.Cqrs
project. They follow the conventions specified in the The Art of Unit Testing: with Examples in .NET by Roy Osherove, which I recommend you read, it is a bit outdated, however, there is a newer version being cooked, while writing this post. AT.Web.Website
: ASP.NET MVC4 project that references AT.Core
and AT.SampleApp.Cqrs
The Code
I felt the best way to show the pattern, is to progress in the code as if I am debugging and show what is happening in each stage, I found this is the fastest way to learn, we spend half our lives as debugging debugging!
The Command
The user clicks the “Completed?” checkbox for one task to mark it as completed, which executes the following JavaScript/jQuery:
$.post("/Task/ChangeTaskStatus",
{
"TaskId": $(this).data("id"),
"IsCompleted": this.checked,
"UpdatedOn": fomattedNow
}
);
Command & Controller
The post request reaches the ChangeTaskStatus
action method and becomes a command:
public class TaskController : Controller
{
private readonly IQueryDispatcher _queryDispatcher;
private readonly ICommandDispatcher _commandDispatcher;
public TaskController(IQueryDispatcher queryDispatcher,
ICommandDispatcher commandDispatcher)
{
_queryDispatcher = queryDispatcher;
_commandDispatcher = commandDispatcher;
}
[HttpPost]
public ActionResult ChangeTaskStatus(ChangeTaskStatusCommand command)
{
_commandDispatcher.Dispatch(command);
return new HttpStatusCodeResult(HttpStatusCode.Accepted);
}
}
Starting by the easier bit of the ChangeTaskStatus
method, the action method returns a HTTP code to the client to say that everything is fine.
Command Dispatcher
_commandDispatcher.Dispatch
takes a command and relies on the dependency injection to find a handler for this command, in this case, it will match the ChangeTaskStatusCommand
with ChangeTaskStatusCommandHanlder
.
Why relying on dependency injection rather than calling the command handler directly? Simple answer: decoupling. The controller doesn’t know much what is happening, it is just dispatching (some calls it publishing, but publishing might convey an async call or a bus call) a command “to whom it may concern” and the proper handler will take it and processes it.
The _commandDispatcher
is injected into the controller as well, we will see what it does in more details, but before that lets look at the dependency injector code, for this, I have used Ninject and Ninject.Extensions.Convention from NuGet, this is the kernel code that I’ve used:
kernel.Bind(x => x.FromAssembliesMatching("AT.Core.dll", "AT.Web.Website.dll")
.SelectAllClasses().BindDefaultInterface());
BindDefaultInterface
is simply saying bind ISomething
to Something
by convention, so, the first line injects the dispatchers into the controller.
Now, this dispatch method, how does it work? How does it match the command to its handler?
public void Dispatch<TParameter>(TParameter command) where TParameter : ICommand
{
var handler = _kernel.Get<ICommandHandler<TParameter>>();
handler.Execute(command);
}
_kernel
is Ninject, it is querying, at run-time, the handler of the passed command and then calling its Execute
method to pass it the command.
You’ve got to like the fact that dependency injectors promote decoupling, but your modules become coupled to them! Maybe we need a second-level dependency injector to decouple the first one. But, Ninject has a cool logo, so I don’t mind my modules depending on it :)
Command Handler
This is where the business logic lives. The handler might mutate a state, save to the DB (or more accurately, persists through a repository), calls another handler, etc…
This is the ChangeTaskStatusCommandHanlder
, Execute method:
public void Execute(ChangeTaskStatusCommand command)
{
if (command == null) { throw new ArgumentNullException("command"); }
if (string.IsNullOrWhiteSpace(command.TaskId)) {
throw new ArgumentException("Id is not specified", "command");
}
var task = _taskRepository.All().Single(x => x.Id == command.TaskId);
task.IsCompleted = command.IsCompleted;
task.LastUpdated = command.UpdatedOn;
_taskRepository.Update(task);
}
Please keep in mind, what we are doing here as a business logic is super simplistic and doesn’t show the true power of the CQRS pattern, but it does give you an idea.
Binding via Ninject (this code will apply to all my handlers, not just this one):
kernel.Bind(x => x.FromAssembliesMatching("AT.SampleApp.Cqrs.dll")
.SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>)).BindAllInterfaces());
Repository
I have used MongoDB as a storage media, which you can NuGet. Also, rather than implementing the popular Repository DDD pattern myself, one good chap implemented it for us for MongoDB and packaged it as NuGet, look at NuGet for MongoRepository. I am simply using it as-is. You could see that from the previous code above. I am using the following Ninject code to bind to it:
kernel.Bind(x => x.FromAssembliesMatching("AT.SampleApp.Cqrs.dll", "MongoRepository.dll")
.SelectAllClasses().InheritedFrom(typeof(IRepository<>)).BindAllInterfaces());
Aggregate
This is a simple aggregate and I am persisting it as a document in MongoDB:
public class Task : IEntity
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Title { get; set; }
public bool IsCompleted;
public DateTime LastUpdated;
}
The Query
The query has a similar path to the command, with the following differences:
- The controller is calling the
_queryDispatcher
explicitly and not implicitly like the _commandDispatcher
. - The query is two ways, the query and its results while the command is one way.
- There are much more differences, but I am looking at the differences from this project point of view.
Recap
I hope that I was able to illustrate the diagram above, feel free to ask me in a comment if I made a mistake or if you have a question.
Let’s recap on the steps that the command of CQRS was implemented.
- Command is triggered by the view.
- Command reaches the action method.
- The action method dispatches the command to a handler.
- The handler takes the command and does some business logic then persists it through a repository.
What’s Next?
This is only the basic and the first building block in your CQRS application. You will probably add other CQRS related pattern on top of this. Here are some ideas to polish your architecture:
Base Controller
You might want to have a Base Controller and inject your dispatchers into it. Something like this:
public abstract class BaseController : Controller
{
[Inject]
public ICommandDispatcher CommandDispatcher { get; set; }
[Inject]
public IQueryDispatcher QueryDispatcher { get; set; }
}
Event Sourcing
Now, you have seen the basic pattern, what about looking further: Here is another good article that has a different focus to the stuff I’ve discussed here: Introduction to CQRS.
Enhancing the basic Architecture
There is no logging, there is no error handling, ofcourse, as this is not meant for production, it meant to be a sample, make it mainstream :)
Conclusion
The results? Controllers are nearly empty, DRY code and a pattern that is open for unit testing. Obviously, the amount of code is over killing for such a small application, but this is only to trigger your software design imagination so you could apply this pattern to a real-life application (obviously not by forcing the pattern if it doesn’t fit).
I hope I made somebody’s day, if you like this then do let me know in a comment so I would be encouraged to write more. While I tried to keep it to a minimum, this was longer than what I wanted it to be. Note that the source code in the download area contains the complete code.
I am open for suggestions to change for the better, do let me know your ideas in a comment.