Skip to content
seif edited this page Jan 22, 2013 · 11 revisions

Recipe #003 - Using Commands

Overview

Inspiration: CQRS a la Greg Young

Lets first consider what would normally happen after receiving a DTO; the user would make changes to the data and save this back to the DTO. This DTO then gets shipped back to the back-end, converted into an entity and the ORM will make sure that the changes are persisted into the database.

This would result in losing some very valuable information; the Why did this change happen? You completely lose the intent the user had when he changed the data, and this is one of the things Greg’s implementation of CQRS is solving.

Commands, CommandHandlers and their Result live in the Controller Layer. A Command is sent to a Handler, and returns a result.

Example Implementation

Command

public class ChangeCustomerAddressCommand : CommandBase
{
    public ChangeCustomerAddressCommand(
                                        int id, 
                                        string addressLine1, 
                                        string addressLine2, 
                                        string city,
                                        string stateProvince,
                                        string postalCode,
                                        string countryRegion)
    {
        this.Id = id;
        this.AddressLine1 = addressLine1;
        this.AddressLine2 = addressLine2;
        this.City = city;
        this.StateProvince = stateProvince;
        this.PostalCode = postalCode;
        this.ModifiedDate = DateTime.Now;
        this.CountryRegion = countryRegion;
    }

    [Required]
    public int Id { get; set; }

    [Required]
    public string AddressLine1 { get; set; }

    public string AddressLine2 { get; set; }

    [Required]
    public string City { get; set; }

    [Required]
    public string StateProvince { get; set; }

    [Required]
    public string PostalCode { get; set; }

    [Required]
    public DateTime ModifiedDate { get; set; }

    [Required]
    public string CountryRegion { get; set; }

}

Handler

public class ChangeCustomerAddressHandler : ICommandHandler<ChangeCustomerAddressCommand>
{
    private readonly INHibernateRepository<Address> addressRepository;

    public ChangeCustomerAddressHandler(INHibernateRepository<Address> addressRepository)
    {
        this.addressRepository = addressRepository;
    }

   public ICommandResult Handle(ChangeCustomerAddressCommand command)
   {
       var customer = this.addressRepository.Get(command.Id);
       customer.ChangeAddress(
           command.AddressLine1,
           command.AddressLine2,
           command.City,
           command.StateProvince,
           command.PostalCode,
           command.CountryRegion);

       this.addressRepository.SaveOrUpdate(customer);
       return new ChangeCustomerAddressResult(true);
   }
}

Result

public class ChangeCustomerAddressResult : CommandResult
{
    public ChangeCustomerAddressResult(bool success) : base(success)
    {
    }
    
    public string Message { get; set; }
}

Controller

    [HttpPost]
    public ActionResult AddressChange(Address viewModel)
    {
        var command = new ChangeCustomerAddressCommand(
                                                       viewModel.Id,
                                                       viewModel.AddressLine1,
                                                       viewModel.AddressLine2,
                                                       viewModel.City,
                                                       viewModel.StateProvince,
                                                       viewModel.PostalCode,
                                                       viewModel.CountryRegion);

        var results = this.commandProcessor.Process(command);

        if (results.Success)
        {
            return this.RedirectToAction(x => x.Index());
        }

        return View(viewModel);
    }