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

PseudoCQRS, a Framework for Developing MVC Applications

Rate me:
Please Sign up or sign in to vote.
4.85/5 (21 votes)
17 Mar 2014CPOL9 min read 45.4K   39   24
This article provides an overview of the PseudoCQRS open source project, a package for use in developing MVC web applications.

An Introduction to PseudoCQRS

Command Query Responsibility Segregation (CQRS) is a pattern that was first described by Greg Young (http://codebetter.com/gregyoung/). You can read about the CQRS pattern here http://martinfowler.com/bliki/CQRS.html and here http://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf

A key concept of the CQRS pattern is that the state of your application is determined based on the events that have happened in the system. This differs from a “standard” N-Tier application where the state of the application is stored in the data store.

In a standard N-Tier application, if you wanted to create a customer you would create a Customer object, and then save that object to the database via some sort of repository (probably via an ORM such as NHibernate). If you then to update the address you would use retrieve the customer from the repository, update it, and then save it via the repository Save method again.

With CQRS, the state of the customer object is held in memory, and the things that you persist to the data store are the actual events that occurred in the system that affected that customer. As you have a record of all those events, if you shut the application down and then start it up again, you can just run through all the events to restore the state of the Customer object, and the rest of the system.

PseudoCQRS was created because we wanted to apply the CQRS pattern to an existing application - one that already has all the state information stored on a database. It was not going to be possible to refactor the application to use a "Pure" CQRS implementation, but we wanted to use the clear segregation between the "Command" side and the "Read" side of the app. So, PseudoCQRS was born.

PsuedoCQS is written in C# and is primarily aimed at Asp.NET MVC applications (versions 3 or 4).

The PseudoCQRS Architecture

As per the CQRS pattern, there are two sides to the PseudoCQRS architecture - the "Command" side and the "Query" side. This separation is shown on the diagram below:

Image 1

As you can see from the diagram, PseudoCQRS is split into two sides; the “Query” side and the “Command” side.

This aligns with the CQRS pattern, which describes the fact that there are two main things your users do within your application – they look at data that is already in there (the “Query” side) and they execute commands which affect that data (the “Command” side).

The Query Side

In the web applications that we write, there are always a set of screens that users use to have a look at the state of their data. Things like “List all the customers”, “Show the details of one customer”, “Show a particular customer’s financial statement”. These screens rarely show all and ONLY all of the data regarding a particular entity within the domain. For example, in the case of the “List all the customers” screen, we only need to show their first name, last name, perhaps their email address and phone number. We don’t need to show their full postal address, the notes field for the customer, their date of birth etc – we just want a subset of the data.

Similarly, on the “Show the details of one customer” page, we need not only all the data from the Customer entity, but we might need some data from OTHER entities too – the country that they live in, or the name of the saleman who first approached this customer, or perhaps all the notes from recent interactions we’ve had with them. So again, we can’t just draw data from the customer entity – we need additional data.

This is the case in almost every screen in our applications – there is some “custom” set of data that we require in order to display the screen.

This is not a new concept in MVC applications – indeed, this is the “M” of MVC – the “Model”, or, as it’s more often referred to, the “ViewModel”.

This ViewModel will be specific to the particular View (ie, the screen) and will probably not be reused in any other screens (a slight caveat here is that there may be PORTIONS of the ViewModel that could be reused across screens – for example, an AddressViewModel or the like), so in PseudoCQRS we take that to the extent that for each ViewModel there is an individual “ViewModelProvider” which is responsible for creating that ViewModel.

ViewModelProviders use a combination of custom SQL statements and ORM queries to retrieve all the data required for the ViewModel, and to build that ViewModel up and return it. Indeed “pure” CQRS goes even further and suggests that you might even have one flattened table per screen that you fill when commands are executed but then can read straight out of on the Query side, so as to make it blazingly fast to query the database. We don’t go quite that far, but we do create custom queries for each ViewModel we need. We usually then use an open source project called “SqlObjectHydrator” to quickly and easily convert those queries into our ViewModels, but we do have instances where we do ORM queries which are then sculpted into the ViewModel as well. The method of building the ViewModel is not important – what is important is that for each View there is one ViewModelProvider which builds up one ViewModel which contains all the data that is required for that View.

This pattern allows us to very specifically concentrate on writing what we need in order to display the data that we need to. There is no concern over reusing bits and pieces of view based objects, which we have found quickly becomes very messy – instead each View, ViewModel and ViewModelProvider has a single concern and does that single concern very well, and very quickly.

Once the ViewModel has been built by the ViewModelProvider, it is passed to the controller that will display it. We have created three base controllers which we use – a BaseReadController, a BaseReadExecuteController and a BaseExecuteController. Each of these base controller has just one action in it – an “Execute” action. ReadControllers just display views (for example, “List Customers”), ExecuteControllers just execute commands (for example, “Delete a customer”) and ReadExecuteControllers do a bit of both (for example, “Display a customer for editing and the execute the command necessary to process that edit).

There is no real requirement to use the base controller that we’ve created, but we find it helps to align the vertical slices of functionality in a better way – one controller, one view, one viewmodel, one viewmodelprovider.

The Command Side

Besides viewing the state of their data, the other thing that users need to do with an application is to alter that state. This is done via the Command side of PseudoCQRS.

Again we use our base controllers for this – our BaseExecuteController for things that are just commands (“Delete this customer”) and BaseReadExecuteController for things that need to display some data first and then execute a command (“Update this customer’s details”).

Execute type controllers accept a ViewModel, try to validate that ViewModel (via the standard MVC validation attributes, or whatever other validation framework you like – we use FluentValidation), and if it validates correct, maps the ViewModel onto a Command and then puts that Command onto the CommandBus to be executed.

The CommandBus receives the command and first runs any validation rules necessary in order to validate the command. These validation rules are business logic type rules – things like “Don’t allow a customer to be deleted if they have pending orders” or “Only allow certain users to delete customers”). The CommandBus Runs these validation rules on the command and if the validation rules all pass, it then looks up the CommandHandler for a particular command.

If it finds a CommandHandler for the Command (ie, something that implements ICommandHandler<T> where T is the type of the Command) it passes the Command to that hander for execution.

The CommandHandler then deals with processing that command. That will usually involve some ORM queries. For example, an UpdateCustomerCommand will have an UpdateCustomerCommandHandler which will need to pull the existing customer from the database via the ORM, update whatever properties it needs to on the Customer entity and then save that Customer back to the database via the ORM.

The other thing that a CommandHandler may do is to publish “Events” to the EventPublisher. For example if a customer were updated, the UpdateCustomerCommandHandler might publish a “CustomerUpdatedEvent” which contained the details of the customer that was updated and the updates that were made. Objects can then subscribe for notification of these events (by implementing the IEventSubscriber<T> interface, where T is the type of the event). EventSubscribers can then do things like email administrators to inform them of the change, or record the history of the change to the database, or send an SMS to the customer when they place an order etc etc. They can even do things like create “flattened” data for the read side of the application, so that side can be more efficient. For example, if a customer creates a new order, and on the customer list screen you always display each customer’s outstanding balance, you could use an EventSubscriber to calculate that outstanding balance and “Cache” it on the Customer table whenever a pertinent event occurred (OrderPlacedEvent or PaymentMadeEvent). That way, when your ViewModelProvider needs to get that data, it doesn’t have to constantly recalculated the customer’s balance when displaying the list – it can just grab the data from the outstanding balance cache.

Conclusion

We wrote PseudoCQRS in order to allow us to use the very clear separation of concerns that the CQRS pattern offers, but while able to reuse the existing data structure (and much of the existing code) for a legacy application. We have since used it to write a completely new application as well, and it is working very well for us.

This article serves as a summary of the architecture. The next article which descibes the query side of PseudoCQRS can be found here:

Pseudo CQRS: The Query Side

PseudoCQRS is an open source project, and the code can be downloaded from GitHub, here: https://github.com/LiquidThinking/PseudoCQRS

Included in the source code is a sample application that implements the "Create Dinner" feature of the NerdDinner sample created by Scott Hansleman for demonstrating the functionality of Asp.NET MVC.

The package is also available on NuGet (package names PseudoCQRS and PseudoCQRS.Mvc4)

How to use PseudoCQRS

- Create an empty asp.net mvc web application project

- Install PseudoCQRS package via Visual Studio's Package Manager Console => install package ( PseudoCQRS | PseudoCQRS.Mvc4 ) for mvc framework 3 or 4.

Pseudo CQRS has no external dependencies other than some standard system assemblies, and System.Web.MVC.dll (version 3 or 4).

License

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


Written By
Founder Liquid Thinking Ltd
United Kingdom United Kingdom
Founder of Liquid Thinking Ltd, supplier of software to league, venue and event managers since 2002

Comments and Discussions

 
QuestionFew things Pin
Sacha Barber23-Jul-15 20:57
Sacha Barber23-Jul-15 20:57 
GeneralMy vote of 5 Pin
Prasad Khandekar8-Jun-14 20:10
professionalPrasad Khandekar8-Jun-14 20:10 
GeneralMy vote of 5 Pin
Renju Vinod19-Mar-14 20:14
professionalRenju Vinod19-Mar-14 20:14 
GeneralMy vote of 5 Pin
Volynsky Alex17-Mar-14 11:06
professionalVolynsky Alex17-Mar-14 11:06 
QuestionMore segregation? Pin
Duncan Edwards Jones17-Feb-14 6:01
professionalDuncan Edwards Jones17-Feb-14 6:01 
AnswerRe: More segregation? Pin
Matthew Davies17-Feb-14 8:23
Matthew Davies17-Feb-14 8:23 
GeneralRe: More segregation? Pin
Duncan Edwards Jones17-Feb-14 21:05
professionalDuncan Edwards Jones17-Feb-14 21:05 
QuestionMixing up terms...? Pin
Jan Hansen17-Feb-14 1:36
professionalJan Hansen17-Feb-14 1:36 
AnswerRe: Mixing up terms...? Pin
Matthew Davies17-Feb-14 8:28
Matthew Davies17-Feb-14 8:28 
QuestionAwesome! And a question about transactions Pin
danito23412-Feb-14 10:09
danito23412-Feb-14 10:09 
AnswerRe: Awesome! And a question about transactions Pin
Matthew Davies13-Feb-14 9:36
Matthew Davies13-Feb-14 9:36 
GeneralRe: Awesome! And a question about transactions Pin
Duncan Edwards Jones17-Feb-14 5:54
professionalDuncan Edwards Jones17-Feb-14 5:54 
QuestionGreat article - muchly appreciated.... Pin
Phil Boyd11-Feb-14 9:45
Phil Boyd11-Feb-14 9:45 
AnswerRe: Great article - muchly appreciated.... Pin
Matthew Davies11-Feb-14 10:06
Matthew Davies11-Feb-14 10:06 
GeneralRe: Great article - muchly appreciated.... Pin
Phil Boyd12-Feb-14 2:33
Phil Boyd12-Feb-14 2:33 
GeneralRe: Great article - muchly appreciated.... Pin
Matthew Davies12-Feb-14 6:29
Matthew Davies12-Feb-14 6:29 
GeneralRe: Great article - muchly appreciated.... Pin
Phil Boyd12-Feb-14 9:03
Phil Boyd12-Feb-14 9:03 
GeneralOK - 1st question.... Pin
Phil Boyd12-Feb-14 2:48
Phil Boyd12-Feb-14 2:48 
GeneralRe: OK - 1st question.... Pin
Matthew Davies12-Feb-14 6:43
Matthew Davies12-Feb-14 6:43 
QuestionVery good article! Pin
Volynsky Alex10-Feb-14 8:28
professionalVolynsky Alex10-Feb-14 8:28 
AnswerRe: Very good article! Pin
Matthew Davies10-Feb-14 22:32
Matthew Davies10-Feb-14 22:32 
GeneralRe: Very good article! Pin
Volynsky Alex11-Feb-14 0:06
professionalVolynsky Alex11-Feb-14 0:06 
QuestionLook forward to seeing more articles about this. Pin
nportelli10-Feb-14 3:05
nportelli10-Feb-14 3:05 
I'm tasked with doing something similar to our application.
AnswerRe: Look forward to seeing more articles about this. Pin
Matthew Davies10-Feb-14 22:32
Matthew Davies10-Feb-14 22:32 

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.