Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

command/query separation command side result needed

I'm trying to create an ASP.NET MVC application with following CQRS pattern (this is my my first taste of CQRS). I understand that the command side, hasn't any result. In this answer, @Johannes Rudolph said if we need a result on command side, we can create an event and subscripe to, to resolve the problem. Now, assume we are createing a login page:

public class AuthController : Controller {

    private ICommandHandler<LoginCommand> _handler;

    public AuthController(ICommandHandler<LoginCommand> handler) {
        _handler = handler;
    }

    public ActionResult Login(LoginModel model) {
        if(ModelState.IsValid) {
            var cmd = new LoginCommand(model.Username, model.Password);
            _handler.Handle(cmd);
            // how to notify about login success or failed?
        }
        return View(model);
    }
}

How can I notify about login command success or failed? I know I can create an event in LoginCommand and subscribe to it in above method. But, my subscribation is a separate method and can not return a (for example:) specified view. See:

    public ActionResult Login(LoginModel model) {
        if(ModelState.IsValid) {
            var result = true;
            var cmd = new LoginCommand(model.Username, model.Password);
            cmd.CommandCompleted += e => { result = e; };
            _handler.Handle(cmd);
            // is this correct?
            if(result)
                // redirect to ReturnUrl
            else
                // something else
        }
        return View(model);
    }

Is this true? Or do you have any better idea? Or am I wrong?

like image 808
amiry jd Avatar asked Sep 15 '12 16:09

amiry jd


2 Answers

As others have said, the Authentication Process is not a very good example for an async command and for CQRS in general. In practice sync request/response is probably a better solution for this.

Now to do this (or any other example) with async commands, you would need to send the command and eventualy query for the result of that command.

The part of sending the command is "simple". I would not inject the handler in the controller, but instead inject something capable of dispatching that command like a Bus that allows you to .Send() the command. The implementation of the bus is irrelevant and could vary from in memory direct dispatcher to the handler to real service bus implementation. To keep track of the command it might be a good idea do generate an identifier in the constructor ( like Guid.NewGuid()) and return that as a sign that the command has been dispatched successfully.

Now from the actual handler of the command you need to publish an event, either UserAuthenticated of AuthenticationFailed that contain the CommandId and any other data that might be relevant, like user name, user roles etc.

In the asp.net application you need to have a subscriber for each of the two events.

Here you have two options:

  1. store the result of the command and wait for the js code to query for it
  2. use something like SignalR to notify the client code of the event.

After submitting the login information, the client code will get back the command Id. Depending on the option you chose, you can either pool for the login status from javascript every X seconds ( option 1 ) or wait to be notified by a mechanism like SignalR ( option 2 ).

Sometimes option 1 is better, sometimes option 2 is better. If you can estimate a value for the pooling interval that will be fast enough and in most of the cases return the result in the first call then option 1 is best. Option 2 is usually best when in most cases the command is considered to be successful ( like order submission ) and you are only interested in the rare occasions when the command fails.

This may sound complicated for the Authentication process, and it truly is, but in general when you design your process and commands for success, and only have very few failing commands this actually works very well.

For other cases you might need to use a combination of the two options - use option 2 to get a notification that the command has been executed and then query a view model for relevant data.

There is one additional option involving and AsyncController, where you send the command and asynchronously wait for the handler to receive the message. I have not used async controllers for this, so the following is just an opinion, but i just feel that if you need to use an async controller you might be better of with a request-response implementation that uses the async controller to minimise the impact on the webserver.

I must warn you that i've seen CQRS abused and forced upon a process that is designed to be sync request-response ( like CRUD operations ) and the results were systems that dealt mode with the actual infrastructure processing of the events then with the actual business logic.

In the end I highly recommend Udi Dahan's writings on the subject of CQRS and SOA, especially the ones where he warns about the misuse os CQRS.

Hope this helps you step in to the great world of CQRS :)

(this ended up to be a lot longer than expected)

like image 105
Iulian Margarintescu Avatar answered Nov 07 '22 10:11

Iulian Margarintescu


CQRS is a nice concept. But it is very hollow. A lot of things can go under its shell. So be careful of what you put there. Think wisely, try and do not be afraid to go back to more simple things.

Treating command can be sync or async depending on your problem. I would not advise to send your command to a bus as your basic architecture. Treating command in a sync way is far more easier to handle in most cases. Usually you send a command that should be valid. (e g: StartDate must not be greater than end date). Then you arrive in your command handler , where you can verify the the validity of your command in the context of your application layer. (e.g. : is the aggregate root "House" that should exists does exist at all?) Finally, your domain handles this command and checks its validity upon domain context , (eg the AR "House" might be performing complex stuff, your command might be part of...)

What do you want out of this command validation flow. well it's up to you. You might be interested in knowing or not that some validations have failed to warn your users. Or throw an exception because this case should not be even handled by any client.

If you go for async, that means that UI is not going to be aware of any problem in the execution of your command. Might work, but in most cases, your client fill a form and is willing to know now if its action has failed or not.

As far as I am concerned the more I explore these patterns (or whatever you decide to call them) , the more I think that async should be treated as exceptions. You should best work full sync for command handling and event projection. and async the part where you need the async trait. You can start full sync and where you see this approach does not fit, well, everything is ready to put things in a bus , and go async.

my two pennies worth for as I recall, I am on my way myself to play with it,

[Edit]

usually, execution of my commands return :

public class CommandValidation 
{

    public List<ValidationMessage> Messages { get; private set; }
}

The CQRS tells me to return void from my method which I do. Every aggregate has a command validation attribute that is being filled during execution of the command. At the end of the execution , I can then return it to the client.

[/Edit]

like image 32
Arthis Avatar answered Nov 07 '22 11:11

Arthis