# Intent.AspNetCore.Controllers.Dispatch.Wolverine

Wires ASP.NET Core controllers generated by Intent Architect to dispatch commands and queries through Wolverine's `IMessageBus`, replacing the default MediatR dispatch with Wolverine's `InvokeAsync` pattern.

## What This Module Generates

This module does not introduce new template files. It hooks into the existing `ControllerTemplate` from `Intent.AspNetCore.Controllers` via a factory extension:

- `WolverineControllerDispatchExtension` — factory extension that finds every generated controller whose model is a `CqrsControllerModel`, injects `IMessageBus _sender` via the constructor, and replaces the dispatch call in each action method with `_sender.InvokeAsync` or `_sender.InvokeAsync<T>`.
- `ImplicitControllerTemplateRegistration` — groups commands and queries that carry HTTP settings by their parent folder element, creating one controller per group.

## Controller Dispatch

For commands that return a result, the generated action uses the typed overload:

```csharp
var result = await _sender.InvokeAsync<Guid>(command, cancellationToken);
```

For void commands (no return type), the non-generic overload is used:

```csharp
await _sender.InvokeAsync(command, cancellationToken);
```

## Constructor Injection

`IMessageBus` is injected through the controller constructor, not as an action-method parameter:

```csharp
public class ProductsController : ControllerBase
{
    private readonly IMessageBus _sender;

    public ProductsController(IMessageBus sender)
    {
        _sender = sender;
    }
}
```

## Generated Controller Shape

A typical controller generated by this module looks like:

```csharp
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IMessageBus _sender;

    public ProductsController(IMessageBus sender)
    {
        _sender = sender;
    }

    [HttpPost]
    public async Task<ActionResult<Guid>> CreateProduct(
        [FromBody] CreateProductCommand command,
        CancellationToken cancellationToken = default)
    {
        var result = await _sender.InvokeAsync<Guid>(command, cancellationToken);
        return CreatedAtAction(nameof(GetProductById), new { id = result }, result);
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<ProductDto>> GetProductById(
        [FromRoute] Guid id,
        CancellationToken cancellationToken = default)
    {
        var result = await _sender.InvokeAsync<ProductDto>(new GetProductByIdQuery(id: id), cancellationToken);
        return result == null ? NotFound() : Ok(result);
    }
}
```

## Command Instantiation

When a command or query model has a parameterized constructor, the generated call uses constructor syntax:

```csharp
new GetProductByIdQuery(id: id)
```

When no parameterized constructor is present, object initializer syntax is used instead:

```csharp
new GetProductByIdQuery { Id = id }
```

## Related Modules

- `Intent.Application.Wolverine` — registers Wolverine in the DI container and provides the `IMessageBus` service that this module dispatches through.
- `Intent.AspNetCore.Controllers` — owns the `ControllerTemplate` that this module extends. Must be installed for this module to function.
- `Intent.Modelers.Services.CQRS` — provides the command and query designer elements that drive controller grouping and action generation.
