Sunday, 31 August 2014

A CQRS Implementation with ASP.Net MVC and Entity Framework

Previous posts in this series

Considering a CQRS approach with ASP.Net MVC

Even a quick read of the various blog posts and other web based information on using CQRS with .Net reveals it can mean a lot of things to different people. To my understanding, at scale, it's a recognition that your read and write operations are likely to require quite different approaches. Reads for example may be coming from denormalised or cached information, and writes might go to queues for subsequent processing. Which is all a bit removed from a more basic CRUD approach where we simple read and write to the database.

In truth though, I didn't need - at least yet - these type of performance improvements. Nonetheless, there remains value for me even in a smaller-scale application in handling query and command operations more distinctly. Which really means in practice that rather than having a service and/or repository layer that provides methods such as GetCustomers, GetCustomerById, SaveCustomer, DeleteCustomer etc. we instead have discrete classes that handle each of these query or command operations. It means more classes for sure, but each one being smaller, more focussed and adhering much more closely to the single responsibility principle.

Another advantage of this approach I find is a better aligning the language of the application or code that of the logic we are looking to model - the ubiquitous language between the developers and the business. One example I had was having user's sign up for a particular event. With the CRUD approach I would likely have created something like an EventUser class - containing references to the Event, the User and some supplementary information such as the date of sign up. And then have a method in my service layer for SaveEventUser().

None of this is really language a business stakeholder would talk - in contrast the creation of a SignUpUserForEvent command does align much more closely.

Finally with this approach I hoped to avoid some issues I've found in the past with a more loose approach to dealing with the Entity Framework context. With this method, we would simply create the context within the query or command object, carry out the read or write operation, save changes and allow the context to go out of scope. With that tighter control there's less room for bugs or unexpected side-effects.

Scenarios

The method I've set up - closely following the example provided by Adam Tibi in his blog post on implementing a CQRS-based architecture with MVC - contains the following, inter-related components:

  • Each controller with functions that require reads (all of them) or writes (some of them) contain dependency injected instances of QueryDispatcher and CommandDispatcher
  • The QueryDispatcher takes type parameters for a query result (or view model) that implements IQueryResult, and a query that implements IQuery. Based on that, using Ninject, the appropriate IQueryHandler is found and executed, passing the query and returning the result.
  • Within the handler, we instantiate the EF context and carry out the appropriate querying and mapping operations to construct the result.
  • Similarly the CommandDispatcher takes a type parameter for the command and the appropriate ICommandHandler is found and executed.
  • Within the handler, we instantiate the EF context and carry outs the appropriate write operation.
  • Command handlers return a simple and standard CommandResult with a status flag, any error messaging and an data object used in cases such as where we need to know the Id of the entity just created.

Given that, we have the following three types of data flow through the application.

Reads

The following diagram illustrates the components involved in handling a read (or query) operation, most usually in the preparation of a view model for presentation of information in a view:

The data flow through these components is as follows:

  • Controller action method takes a parameter of type IQuery. This might be as simple as an Id for the record to display, or something more complex like a set of search parameters.
  • The controller action calls the query dispatcher, passing the query along with the type parameters for the query and the view model (which implements IQueryResult).
  • The appropriate IQueryHandler is called, which uses the EF context to get the data specified by the query and AutoMapper to map or project it into the view model.
  • The view model is passed to the strongly typed view.
Writes

A similar pattern but involving different components handles a write (or command) operation, processing updates that come direct from a form post, an example being the sign-up of a user for an event which comes from a form posting the Id of the event:

Again, to further describe this process:

  • Controller action method takes a parameter of type ICommand that is constructed via MVC model binding from the form post.
  • Further parameters as appropriate are added to the command object (e.g. the Id of the logged in user).
  • The controller action calls the command dispatcher, passing the command along with the type parameter for the command.
  • The appropriate ICommandHanlder is called, which uses the EF context to carry out some validation and make the appropriate model updates.
  • A standard CommandResult object is returned containing a success flag, any error messages and where useful, any response data (such as the Id of the newly created record).
Validated Writes

A complication arises when we come to consider validation. Normally with ASP.Net MVC we'll handle this with data annotations on our view model, which tie in nicely with the framework to provide both server and client side validation. I don't want to lose that facility by say moving the validation up to the command handler. But equally, it doesn't seem right to be passing the view model itself as the command object - the former being clearly part of the presentation layer, not something for data processing.

The way I handle this is to post the view model and handle validation as per usual MVC model binding and validation patterns. If validation passes, I map the view model to a command object, and then continue as per the "Writes" example above.

]

Once more to flesh this diagram out a bit.

  • The presentation of the form data on first load is handled as per "Reads" above.
  • The form post controller action method takes an instance of the view model that is constructed via MVC model binding from the form post/
  • Validation is carried out both client and server side using standard MVC techniques with ModelState.
  • If validation failed, the view model is repopulated with any supplementary information that hasn't been passed in the form post (e.g. the options in selection lists) and returned to the view.
  • If validation passes the view model is mapped (using AutoMapper) to a command object that implements ICommand.
  • From here on we proceed as per "Writes" above.

An end-to-end code example

This example presents the various code excepts that implement this pattern, for the example of a simple process to present a form for editing, validate the submission and process the update.

Set-up

The first step is to create the necessary components for the actual query and command handling - this includes the handler itself, but also various marker interfaces that will be used in the process of matching the appropriate handler from a given query or command.

Firstly for queries:


    // Marker interface to signify a query - all queries will implement this
    public interface IQuery
    {        
    }
 
    // Marker interface to signify a query result - all view models will implement this 
    public interface IQueryResult
    {
    } 
 
    // Interface for query handlers - has two type parameters for the query and the query result
    public interface IQueryHandler<TParameter, TResult> 
       where TResult : IQueryResult
       where TParameter : IQuery
    {
        Task<TResult> Retrieve(TParameter query);
    } 

    // Interface for the query dispatcher itself
    public interface IQueryDispatcher
    {   
        Task<TResult> Dispatch<TParameter, TResult>(TParameter query)
            where TParameter : IQuery
            where TResult : IQueryResult;
    }
 
    // Implementation of the query dispatcher - selects and executes the appropriate query
    public class QueryDispatcher : IQueryDispatcher
    {
        private readonly IKernel _kernel;

        public QueryDispatcher(IKernel kernel)
        {
            if (kernel == null)
            {
                throw new ArgumentNullException("kernel");
            }

            _kernel = kernel;
        }

        public async Task<TResult> Dispatch<TParameter, TResult>(TParameter query)
            where TParameter : IQuery
            where TResult : IQueryResult
        {
            // Find the appropriate handler to call from those registered with Ninject based on the type parameters
            var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>();
            return await handler.Retrieve(query);
        }
    } 

And similarly for commands:


    // Marker interface to signify a command - all command will implement this
    public interface ICommand
    {        
    }
 
    // Interface for command handlers - has a type parameters for the command
    public interface ICommandHandler<in TParameter> where TParameter : ICommand
    {
        Task<CommandResult> Execute(TParameter command);
    } 
 
    // Simple result class for command handlers to return 
    public class CommandResult
    {
        public bool Success { get; set; }

        public string Message { get; set; }

        public object Data { get; set; }
    } 
 
    // Interface for the command dispatcher itself
    public interface ICommandDispatcher
    {
        Task<CommandResult> Dispatch<TParameter>(TParameter command) where TParameter : ICommand;
    } 
 
    // Implementation of the command dispatcher - selects and executes the appropriate command 
    public class CommandDispatcher : ICommandDispatcher
    {
        private readonly IKernel _kernel;

        public CommandDispatcher(IKernel kernel)
        {
            if (kernel == null)
            {
                throw new ArgumentNullException("kernel");
            }

            _kernel = kernel;
        }

        public async Task<CommandResult> Dispatch<TParameter>(TParameter command) where TParameter : ICommand
        {
            // Find the appropriate handler to call from those registered with Ninject based on the type parameters  
            var handler = _kernel.Get<ICommandHandler<TParameter>>();
            return await handler.Execute(command);
        }
    }

We then need to register these types with our IoC container, in this case Ninject. This will include the dispatcher classes, and setting up the registration of the query and command handlers too.


 kernel.Bind<IQueryDispatcher>().To<QueryDispatcher>();
 kernel.Bind<ICommandDispatcher>().To<CommandDispatcher>();

 kernel.Bind(x => x
  .FromAssembliesMatching("MyApp.dll")
  .SelectAllClasses().InheritedFrom(typeof(IQueryHandler<,>))
  .BindAllInterfaces());

 kernel.Bind(x => x
  .FromAssembliesMatching("MyApp.dll")
  .SelectAllClasses().InheritedFrom(typeof(ICommandHandler<>))
  .BindAllInterfaces());

Form display

The first part of the example itself requires the display of an item for editing on a form. This involves handling the request that comes into the controller action, determining the appropriate handler, executing it to populate a view model and passing this to a strongly typed view.


    // Controller action method taking a query that consists of just the Id for the item to be edited
    public async Task<ViewResult> Edit(EditViewModelQuery query)
    {
        // Populate the view model by calling the appropriate handler
        var vm = await QueryDispatcher.Dispatch<EditViewModelQuery, EditViewModel>(query);
        if (vm.Id == 0)
        {
            throw new HttpException(404, "Page not found");
        }

        return View(vm);
    }
    
    // Query handler Retrieve method implementation
    public async Task<EditViewModel> Retrieve(EditViewModelQuery query)
    {
        // Instantiate the context (if not passed to the handler, which will only be the case when unit testing)
        Context = Context ?? new ApplicationDbContext();

        // Create the view model query result
        var result = new EditViewModel();
        
        // Pull the required item from the context
        var activity = await Context.Activities
            .SingleOrDefaultAsync(x => x.Id == query.Id);
            
        // Map from the domain model object to the view model
        Mapper.Map(activityType, result);

        return result;
    }
    
    @using (Html.BeginForm("Edit", "Activities", FormMethod.Post))
    {
        @Html.LabelFor(m => m.Name)
        @Html.EditorFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name)

        <input type="submit" value="Save" />                    

        @Html.HiddenFor(model => model.Id)    
    } 

Processing of form submission

Once the form is posted, it'll be picked up by another controller action expecting a POST input of an instance of the view model. This will be validated, and if it passes, a command object created and mapped. This command will be passed to the appropriate handler for execution and the result returned for subsequent processing.


    // Controller action method handling the form post
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(EditViewModel vm)
    {
        // First check if view model is valid
        if (ModelState.IsValid)
        {
            // If so create the command object
            var command = new AddOrEditCommand();
            
            // Use Automapper to map from the view model to the command
            Mapper.Map(vm, command);
            
            // Call the appropriate command handler
            var commandResult = await CommandDispatcher.Dispatch(command);
            if (commandResult.Success)
            {
                // If the command is successful, we can retrieve any data returned
                var newId = (int)commandResult.Data;

                // Do stuff with the generated Id of the entity if we need to...
                    
                return RedirectToAction("Index");
            }        
            else
            {
                // Command not successful, so handle error as appropriate
            }
        }

        // View model not valid, so return to view
        return View("Edit", vm);
    }
    
    // Command handler Execute method implementation    
    public async Task<CommandResult> Execute(AddOrEditCommand command)
    {
        ValidateArguments(command);
        
        // Instantiate the context (if not passed to the handler, which will only be the case when unit testing)
        Context = Context ?? new ApplicationDbContext();

        var result = new CommandResult();
        var commandValid = false;
        Activity activity;
        
        // If a new record, create a new entity, map the command to the domain object and add it to the context
        if (command.Id == 0) 
        {
            activity = new Activity();
            Mapper.Map(command, activity);
            Context.ActivityTypes.Add(activity);
            commandValid = true;
        }
        else 
        {
            // If an updated record, retrieve it from the context and apply the updates
            activity = await Context.Activities.SingleOrDefaultAsync(x => x.Id == command.Id);
            if (activityType != null) {
                Mapper.Map(command, activity);
                commandValid = true;
            }
            else {
                result.Message = "Activity type not found.";
            }
        }
        
        if (commandValid) 
        {
        
            // Commit data  changes
            await Context.SaveChangesAsync();
            
            // Prepare result
            result.Success = true;
            result.Data = activityType.Id;
        }
        
        return result;
    }    

21 comments:

  1. Andy, could you make the source code for the whole sample available?

    Thanks! Nice article.

    ReplyDelete
    Replies
    1. @Steven check out
      http://www.adamtibi.net/06-2013/implementing-a-cqrs-based-architecture-with-mvc-and-document-db
      There's a link to download a solution at the bottom of that page that's very similar to what's described above; with the exception that's it's not async based (though it would be pretty easy to make it async).

      Delete
    2. Yes, have referenced that post above - was the main source of inspiration for this.

      Delete
  2. It's pulled out of a client project, so I couldn't I'm afraid - but the various pieces are all in the post above.

    ReplyDelete
  3. Thanks for the example - I am new to CQRS and this helps.
    A question if I may! Are the commands meant to be similar to domain objects? The usage of: Mapper.Map(command, activity); suggests that they are, however I wouldn't have thought that this was often the case. I'm picturing for example, a "ShipOrderCommand" - it contains the information necessary to ship the order (i.e the order id) but it has nothing to say about your domain model. To process the order shipping in terms of the domain model would probably require all sorts of interactions with domain objects. Am I missing something here or is the usage of the Mapper just a happy coincidence in this scenario, or are you suggesting that you should always be able to map commands to domain objects?
    Thanks

    ReplyDelete
  4. Hi Darrell - thanks for the comment. It's not the case that I see commands as domain objects no, but it's good you pointed out as I can see that I've made it look like that. I agree with your view that the command object should contain only the information necessary to perform the write operation - so in your case with a "ShipOrderCommand" it would likely contain only the order Id and perhaps the date.

    Rather it just happens that the command I've used to illustrate my example called "AddOrEditCommand" comes from an example where I need to add (or edit) an Activity (which is a domain object) record. Given the command contains fields like the activity name, location, date that do map to fields on the domain object, I've used Automapper to perform this update. It's as you say a happy coincidence (or perhaps laziness!) on my part that I've done that.

    ReplyDelete
  5. Thanks for the post. I am a bit confuse about the implementation of the execute and retrieve methods of the handlers. did you just create an action in the controller

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. Hi Kilfay - no, these sit in a separate class, the query handler or command handler as referenced in the diagrams above, something like:

    public class MyQueryHandler : IQueryHandler[MyViewModeQuery, MyViewModel]
    {
    public async Task Retrieve(MyViewModelQueryquery) {}
    }

    (Note the square brackets above should be angle brackets, but the commenting tool swallows them).

    ReplyDelete
  8. How do you handle business logic which means you need to keep the context around?

    I need to load an object, check some state, possibly load another object, check it's state and then save the initial object with some changes. I can move all that logic into the command but that's not really giving it a single responsibility.

    I'm currently using a per-request lifetime manager for my DI container and injecting the context into the commands. Calling the command from the BL is then a 2 step process, var toEdit = command.load(); var info = query.getMoreInfo(); toEdit.Something = newValue; command.saveChanges();

    The issue i feel is that having that shared context means that any "accidental" changes to info will also be saved. The pattern isn't very clean.

    ReplyDelete
  9. Interesting one. I think probably if it were me I'd consider that one "responsibility" and be fine with it in the command. It involves a bit of a logic and additional queries as you say, but it's all to the same end of "updating an object". So feels OK to me... but you or others may disagree.

    One thing you could perhaps do though is in your query.getMoreInfo() use AsNoTracking()? That way if you did - inadvertently - change any properties on that object they wouldn't get flushed to the database on SaveChanges().

    ReplyDelete
  10. how do you handle exception when executing command. I see CommandResult have a Success property. Is this property used just for 'business command validation' (e.g. object is not in a valid state for the command) or u use it also for unexpected exceptions and handle all the exception in the CommandHandler?

    P.S. : great session at WEC in Milan.

    ReplyDelete
  11. I'd usually be considering three types of validation here.

    Firstly, if the command has come from a form post with a number of fields, I'd have presented this as a view model with validation in the form of validation attributes. I'd ensure the view model was valid before creating the command (and if not return to the view in the usual MVC way). So that would deal with things like required fields, string lengths and the like.

    Then as you say there's "business command validation". Things like checking a submitted value is valid based on other things you might need to query (e.g. a unique email address for a registration form). In those cases I'd return a message and success = false flag in the CommandResult and act on that in the controller to add an error to the ModelState and return to the view.

    And then there's unexpected exceptions. In that case there's a couple of options - if they are potentially recoverable, could put the try/catch in the command handler. But normally I'd just let them bubble up to the controller and handle them there with some error handling that logs the error and present a "unexpected error" page.

    PS: Thanks!

    ReplyDelete
  12. After dealing with service classes, repositories, unit of work patterns and all that guff I've come to the same architectural conclusion as you - glad to see someone else with the same thoughts!

    ReplyDelete
  13. That's provided by Ninject.

    ReplyDelete
  14. Hi,
    First of all thanks for the write up, it was a great read.

    I am curious how this handles commands asynchronously, since command handlers are suppose to be "fire and forget" returns nothing (void). However in your example you return CommandResult, wouldn't this cause a deadlock?

    ReplyDelete
  15. No, it won't deadlock. It's using asynchronous methods in the sense of using async/await, which allow the application to continue to do other work when waiting for relatively slow operations to complete - such as database access.

    But it's not asynchronous in the sense of fire and forget. I am waiting for a response from the command to be able to indicate the caller if it were successful or not. Some might say that's a deviation from true CQRS but I think it's also valid to say normally you do want to have the caller know something has successfully accepted.

    Now it might be you still would want to process the command in a true asynchronous pattern, if it were really slow like perhaps generating a report. I've not done that here but for some applications (or some commands within an application) it might be useful. Even then though, you would probably still want your command to acknowledge the request with a command result - and so not be true fire and forget. That request then might be saved to a queue to be processed via another application.

    There's more on this here: https://lostechies.com/jimmybogard/2012/08/22/busting-some-cqrs-myths/ - see "myth 4"

    ReplyDelete
  16. Hi Andy!
    I am new to CQRS.... I read the your blog.. but as not too expert i am unable to get hole CQRS implementation process. So i request you to provide the sample code of said example of your blog.

    Thank You :)

    ReplyDelete
  17. It's pulled out of a client project, so I couldn't I'm afraid - but the various pieces are all in the post above.

    You might want to check out this library though: https://github.com/jbogard/MediatR. Released since this post was written it takes a similar approach and is well documented. I've switched to using it now.

    ReplyDelete