"hello world" CommandsFeature not working

Trying to implement my first CommandsFeature and am getting the error “No service for type ‘DVApi.Interface.wOBACalculatorCommand’ has been registered”.

public class wOBACalculatorCommand(
    ICacheClientAsync cacheClientAsync,
    IServiceGatewayAsync gatewayAsync,
    ILogger<wOBACalculatorCommand> log)
    : AsyncCommandWithResult<wOBACoefficients, wOBACoefficients>
{
    protected override async Task<wOBACoefficients> RunAsync(wOBACoefficients req, CancellationToken token)
    {
        log.LogInformation("Got to wOBA command");
        return req;
    }
}

I have registered the plugin like so

[assembly: HostingStartup(typeof(DVApi.ConfigureCommands))]

namespace DVApi;

public class ConfigureCommands : IHostingStartup
{
    public void Configure(IWebHostBuilder builder) => builder
        .ConfigureServices((ctx, services) =>
        {
            services.AddPlugin(new CommandsFeature());
        });
}

and here is how I am trying to call it…

public class DashService(ICommandExecutor cmdExecutor) : DVService
{
    public async Task<DashPitcherBattedBallResponse> GetAsync(DashPitcherBattedBall req)
    {
        var resp = new DashPitcherBattedBallResponse();
        resp.PopulateWith(req);

        var cmd = cmdExecutor.Command<wOBACalculatorCommand>();
        await cmd.ExecuteAsync(new wOBACoefficients());

        return resp;
    }
}

Are commands located in the same assembly as your ServiceStack Services? (e.g. DashService).

Does your App use Endpoint Routing and ASP .NET Core IOC?

1 Like

Thank you for the prompt reply, the issue was that I am not using Endpoint Routing, and I won’t be able to without a big refactor, so I’ll have to skip Commands for now.

You shouldn’t need to, but it’s not able to find your command types.

You could use a custom Type Resolver that returns the command types, e.g:

services.AddPlugin(new CommandsFeature {
    TypeResolvers =
    {
        // Return all Command Types in this Assembly
        () => typeof(wOBACalculatorCommand).Assembly.GetTypes()
            .Where(x => x.HasInterface(typeof(IAsyncCommand))),

        // Or any other way to return an array of command types, e.g:
        () => [typeof(wOBACalculatorCommand)],
    }
});

You could also explicitly register each command, e.g:

services.AddTransient<wOBACalculatorCommand>();

That was my problem with trying out the commands feature, you have to have them in the same assembly as your services. Once I figured that out it worked fine.

1 Like