Click here to Skip to main content
15,867,453 members
Articles / Web Development / ASP.NET

Implementing a CQRS-based Architecture with MVC and Document DB

Rate me:
Please Sign up or sign in to vote.
4.78/5 (9 votes)
22 Jun 2013CPOL8 min read 37.8K   928   27   4
A typical implementation of a CQRS pattern ASP.NET MVC 4, Ninject and MongoDB. I will be demonstrating a sample applications that acts as a base building block for a CQRS-based architecture.

MVC MongoDB Ninject CQRS

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

Task App

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.

ASP.NET MVC with CQRS

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

VS MVC CQRS Solution

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);
    }

    // other action methods
}

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

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United Kingdom United Kingdom
Passionate about refining software practices, promoting self-motivated teams and orchestrating agile projects.
Lives in London, UK and works as a .NET architect consultant in the City.

Blog AdamTibi.net.

Comments and Discussions

 
QuestionThanks! Pin
morzel26-Jun-13 1:30
morzel26-Jun-13 1:30 
AnswerRe: Thanks! Pin
Adam Tibi26-Jun-13 5:29
professionalAdam Tibi26-Jun-13 5:29 
QuestionReal-word example Pin
qwe.net24-Jun-13 21:34
qwe.net24-Jun-13 21:34 
AnswerRe: Real-word example Pin
Adam Tibi24-Jun-13 22:10
professionalAdam Tibi24-Jun-13 22:10 
Thank you.
Unfortunately and you would have probably guessed my answer, I cannot provide a real sample due to business reasons.
I usually handle errors with the ComponentModel namespace, in the command and the query and return back to the user if there is an error after checking ModelState.IsValid .

For extending the command and the query, have a look at the article on CP that I've referenced, in the What's Next section, about Introduction To CQRS, it is taking this sample a step further.
Make it simple, as simple as possible, but not simpler.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.