Skip to content

7. HTTP Dispatch and Execution

James Randall edited this page Feb 20, 2018 · 4 revisions

Applies to v5.0.0 and higher. See revision history for documentation for prior versions.

To understand this it's best to look at the client sample and the server sample however I'll cover getting started with this here. First you'll need to add the NuGet package:

Install-Package AzureFromTheTrenches.Commanding.Http

Registration of a command is, optionally, slightly different if you want to use HTTP as you don't need to register an actor and you'll also need to install the HTTP handlers:

resolver.UseHttpCommanding();
IHttpCommandDispatcherFactory httpCommandDispatcherFactory = resolver.Resolve<IHttpCommandDispatcherFactory>();
registry.Register<AddCommand, MathResult>(() => httpCommandDispatcherFactory.Create(uri, HttpMethod.Put));

There's nothing stopping you registering an actor too - but it won't do anything as the provided dispatcher will simply not execute actors locally (though it is possible to write a dispatcher that does execute locally and dispatch remotely). Note also above that you can specify both URI and HTTP verb for the command.

Dispatching the command is exactly the same as for in process immediate execution (other than that it will take a little longer):

MathResult mathResult = await commandDispatcher.DispatchAsync(new AddCommand { FirstNumber = 5, SecondNumber = 6});
Console.WriteLine(mathResult.Value);

Hopefully the above illustrates how you can change how commands are executed without changing your code, instead like with an IoC container, just the configuration.

To execute the command in the HTTP server (and I'm assuming you're using Web API or ASP.Net Core MVC in the below) then you need to inject an instance of ICommandExecuter into your controller and execute the command (you could also use the ICommandDispatcher interface if you wish to take advantage of its broader functionality). In ASP.Net Core MVC this looks like the below:

[Route("api/[controller]")]
public class AddController : Controller
{
    private readonly IDirectCommandExecuter _commandExecuter;

    public AddController(IDirectCommandExecuter commandExecuter)
    {
        _commandExecuter = commandExecuter;
    }

    [HttpPut]
    public async Task<MathResult> Put([FromBody]AddCommand command)
    {
        UpdateResult result = await _commandExecuter.ExecuteAsync<AddCommand, MathResult>(command);
        return result;
    }        
}

There's nothing special about the configuration on the server side. In fact it looks exactly like our in memory example from earlier but simply sits in the ConfigureServices method of the ASP.Net Core startup class:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc();
    ICommandingDependencyResolver commandingDependencyResolver = new CommandingDependencyResolver(
        (type, instance) => serviceCollection.AddSingleton(type, instance),
        (type, impl) => serviceCollection.AddTransient(type, impl),
        type => serviceProvider.GetService(type)
    );
    commandingDependencyResolver
        .UseCommanding()
        .Register<UpdatePersonalDetailsCommand, UpdatePersonalDetailsCommandActor>();
}

By default the built in serializer use JSON however you can supply an alternative serializer by implementing the IHttpCommandSerializer interface and registering it when you install HTTP commanding, for example:

resolver.UseHttpCommanding<MyCustomSerializer>();

The IHttpCommandSerializer interface defines methods for serializing, deserializing and stating the MIME / media type.

Note: you'd be correct in assuming I've got some additional functionality coming that allows you to set up the REST API for a command automatically without the above boilerplate controller and action handler