A. Gladkiy A. Gladkiy - 1 month ago 10
C# Question

Injecting IHttpContextAcessor into a Binding Model inside an Controller Action

I have a controller action method:

public void Register([FromBody]RegisterTenantCommand message)
{
...
}


And I have class RegisterTenantCommand with constructor:

public class RegisterTenantCommand
{
public RegisterTenantCommand(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor) { }
}


But when I launch my app and execute this action, I have httpContextAccessor = null.

How can I resolve this?

Answer

Seems you are confusing commands with commands from UI frameworks (like WPF+MVVM implementation of ICommand interface).

The current implementation also kind of violates the SRP principle, where a class should only be responsible for one thing. You're basically handing input (binding it to the user values) and executing it as well as handling the execution logic in it.

Commands in Command/Handler or CQRS pattern are mere messages, they only contain data (which may or may not be serialized and sent via message bus to be processed by other background processes).

// ICommand is a marker interface, not to be confused with ICommand from WPF
public class RegisterTenantCommand : ICommand
{
    public string TenantId { get; set; }
    public string Name { get; set; }
}

The command handler is consists if an marker interface and an implementation of it (1:1 relation, exactly 1 handler for 1 command).

public interface ICommandHandler<T> where T : ICommand
{
    void Handle(T command);
}

public class RegisterTenantCommandHandler : ICommandHandler<RegisterTenantCommand>
{
    private readonly IHttpContext context;

    // You should really abstract this into a service/facade which hides
    // away the dependency on HttpContext
    public RegisterTenantCommandHandler(IHttpContextAccessor contextAccessor)
    {
        this.context = contextAccesspor.HttpContext;
    }

    public void Handle(RegisterTenantCommand command)
    {
        // Handle your command here
    }
}

Once registered either automatically when using 3rd party IoC like Autofac or manually with built-in IoC (here I'll use built-in):

services.AddTransient<ICommandHandler<RegisterTenantCommand>, RegisterTenantCommandHandler>();

You can inject it, either in action or controller or any other service:

public class TenantController 
{
    public TenantController(ICommandHandler<RegisterTenantCommand> registerTenantHandler)
    {
        ...
    }
}

or action

public Task<IActionResult> RegisterTenant(
    [FromBody]RegisterTenantCommand command,
    [FromService]ICommandHandler<RegisterTenantCommand> registerTenantHandler
)
{
    registerTenantHandler.Handle(command);
}

Of course you can abstract this further to only inject one single interface class which will resolve and handle all commands, then call it generalCommandHandler.Handle(command) and its implementation would resolve and handle it.