Click here to Skip to main content
15,889,527 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.9K   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 
Interesting question, and one that we were having a debate about just last week!

At the moment, event subscribers must implement the IEventSubscriber<T> interface, and that interface declares a boolean property IsAsynchronous. If the implementing object returns true from that property, the event subscriber is run on another thread. If it returns false, it's run on the same thread as the object that put the event on the event bus in the first place.

So, if you want your event subscribers to run in the same context as the rest of your command handler, you can just have them return "false" from the IsAsynchronous property. Then, if any errors occur in them, you can roll back whatever transaction you are currently in the context of, and everything's hunky dorey. (In our case we decorate our command controllers with a DbTransaction attribute which starts an NHibernate transaction and does all the db work within that transaction so if anything goes wrong, it can be rolled back accordingly).

HOWEVER, I actually think the IEventSubscriber interface should NOT have an IsAsynchronous property. I think that ALL event subscribers should be run asynchronously. I think they should be for things like emailing out notifications, tweeting results etc - things that are fire and forget. I think that if an event subscriber needs to be run synchronously, then it is not really an event subscriber, and instead should be part of the command handler.

Adeel, who was arguing against this was arguing that the event subscribers provide an excellent way of separating concerns - each event subscriber deals with one thing and one thing only, so it seems a great way to achieve the all important SRP.

What we sort of agreed on is that perhaps there should be TWO event publishers; one for command based events that should run in the context of the same thread/transaction and one for "fire and forget" type events (after all, you probably wouldn't want to roll back a transaction just because your SMTP server was momentarily down).

What's a greyer area is event subscribers for updating the read model... Is that a critical part of the transaction or not? If that bit fails, should the rest of the command fail too? Another key facet of CQRS as described by Greg Young is that the read model is ALWAYS out of date - as soon as you load a list of customers onto your screen, it may ALREADY be out of date, as someone else may have already added another customer to the application. So if your read model is always inherently a bit out of date, what does it matter if the read model is updated asynchronously? Perhaps with some sort of SignlR mechanism for indicating "New customers have been added! Click here to refresh the page".

But the difference with PseudoCQRS and "pure" CQRS in this regard is that with pure CQRS you can always get back to the point where the read model is correct by just running through your event store again to restore the "true" state of your application. In PseudoCQRS, if an event which updates the read model fails, there isn't really a record of the event that caused the read model to need updating, so that data is sort of lost in the ether. The only thing you could do would be to have some sort of "ReadModelRegenerator" or something like that that ran periodically to make sure everything was up to date.

So, long story short, I'm not really sure... Smile | :)
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 
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.