redb.Route.Controllers 4.2.3

Prefix Reserved
dotnet add package redb.Route.Controllers --version 4.2.3
                    
NuGet\Install-Package redb.Route.Controllers -Version 4.2.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="redb.Route.Controllers" Version="4.2.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="redb.Route.Controllers" Version="4.2.3" />
                    
Directory.Packages.props
<PackageReference Include="redb.Route.Controllers" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add redb.Route.Controllers --version 4.2.3
                    
#r "nuget: redb.Route.Controllers, 4.2.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package redb.Route.Controllers@4.2.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=redb.Route.Controllers&version=4.2.3
                    
Install as a Cake Addin
#tool nuget:?package=redb.Route.Controllers&version=4.2.3
                    
Install as a Cake Tool

redb.Route.Controllers

Transport-agnostic controller dispatch for the redb.Route ESB framework.
Provides a RedbController base class, attribute-based routing, parameter binding, and five dispatcher implementations for generic, HTTP, SOAP, SignalR, and gRPC transports with 16 DSL extension methods. Controllers are transport-unaware — the same controller class works behind any InOut endpoint.

NuGet License: Apache 2.0

Quick Start

// Define a controller
[Route("orders")]
public class OrdersController : RedbController
{
    [HttpGet("{id}")]
    public Task<Order> GetOrder(int id)
    {
        return Task.FromResult(new Order { Id = id, Title = "Sample" });
    }

    [HttpPost]
    public Task CreateOrder([FromBody] Order order)
    {
        // Access route context and exchange
        var ctx = Context;
        var exchange = Exchange;
        return Task.CompletedTask;
    }
}

// Register and dispatch (generic)
var registry = new ControllerRegistry();
registry.RegisterAssembly(typeof(OrdersController).Assembly);

route.From("direct://api")
     .RedbController(registry);

// Or single controller shorthand
route.From("direct://api")
     .RedbController<OrdersController>();

Architecture

This is not a connector (no IComponent, no URI scheme, no producer/consumer). It is a processing library that provides IProcessor implementations and DSL extension methods. Controllers sit behind direct: or transport endpoints and dispatch based on headers set by the upstream consumer.

HTTP Consumer → [redbHttp.Method, redbHttp.Path] → HttpControllerDispatcher → OrdersController.GetOrder()
SOAP Consumer → [redbSoap.operation]             → SoapControllerDispatcher → AirController.GetFares()
SignalR Hub   → [redbSignalR.Method]              → SignalRControllerDispatcher → ChatController.Send()
gRPC Service  → [dispatch-method]                 → GrpcControllerDispatcher → CalcController.Add()
Any Endpoint  → [route.method, route.path]        → ControllerDispatcherProcessor → generic dispatch

RedbController Base Class

All controllers inherit from RedbController, which exposes:

Property Type Description
Context IRouteContext Route context for the current invocation
Exchange IExchange Current exchange being processed

Controllers are instantiated per-request via Activator.CreateInstance(). No DI constructor injection — use Context to access services.

Attributes

Route Attribute

Applied to the controller class. Sets the base path for all actions:

[Route("modules")]           // explicit path
public class ModulesController : RedbController { }

// If omitted, defaults to class name minus "Controller" suffix, lowercased:
public class UsersController : RedbController { }  // base path: "users"

HTTP Method Attributes

Applied to public methods. Define the HTTP method and optional sub-template:

Attribute Method Example
[HttpGet] GET [HttpGet], [HttpGet("{id}")]
[HttpPost] POST [HttpPost], [HttpPost("batch")]
[HttpPut] PUT [HttpPut("{id}")]
[HttpDelete] DELETE [HttpDelete("{id}")]
[HttpPatch] PATCH [HttpPatch("{id}")]

Templates support {param} placeholders that are extracted from the request path and matched to method parameters by name.

Binding Attributes

Attribute Source Example
[FromBody] exchange.In.Body [FromBody] Order order
[FromHeader("X-Tenant")] exchange.In.Headers["X-Tenant"] [FromHeader("X-Tenant")] string tenant
[FromQuery("page")] Query parameter [FromQuery("page")] int page
[FromRoute("id")] Route template {id} [FromRoute("id")] int id
[FromProperty("user")] exchange.Properties["user"] [FromProperty("user")] User user

Implicit binding (no attribute):

  • CancellationToken → CancellationToken.None
  • Parameter name matches a route template {param} → bound from route
  • Complex type → deserialized from body
  • Simple type with default value → uses default

Conversion. Header, query, route and property values are parsed with the invariant culture (12.5 is twelve and a half on every server). A value that is missing binds as the parameter's default (or the type's). A value that is present but does not convert is a binding error naming the parameter and the value, as Camel's ParameterBindingException: the dispatchers answer 400, SOAP a Sender fault, a direct invoke fails the exchange.

Dispatchers

ControllerDispatcherProcessor (Generic)

Reads route.path and route.method headers. Works with any transport.

// Set headers before dispatch
exchange.In.Headers["route.path"] = "orders/42";
exchange.In.Headers["route.method"] = "GET";

// DSL
route.From("direct://api").RedbController(registry);
route.From("direct://api").RedbController<OrdersController>();
route.From("direct://api").RedbController<OrdersController>("GetOrder"); // direct method call

HttpControllerDispatcher

Reads redbHttp.Method and redbHttp.Path headers (set automatically by the HTTP consumer). Also merges redbHttp.RouteParam.* and reads redbHttp.QueryParam.* for parameter binding.

route.From("http://0.0.0.0:8080/api")
     .RedbHttpController(registry);

route.From("http://0.0.0.0:8080/api")
     .RedbHttpController<OrdersController>();

SignalRControllerDispatcher

Reads redbSignalR.Method header. Parameters are resolved positionally from the exchange body (as sent by the SignalR client).

route.From("signalr://bridge")
     .RedbSignalRController<ChatController>();

// Multiple controllers
route.From("signalr://bridge")
     .RedbSignalRController(typeof(ChatController), typeof(NotificationController));

// Method resolution: "Send" or "Chat.Send" (qualified)

GrpcControllerDispatcher

Reads dispatch-method header from gRPC metadata. Body is treated as JSON — single value or array of positional arguments.

route.From("grpc://0.0.0.0:5000")
     .RedbGrpcController<CalcController>();

// Multiple controllers
route.From("grpc://0.0.0.0:5000")
     .RedbGrpcController(typeof(CalcController), typeof(DataController));

SoapControllerDispatcher

Reads the redbSoap.operation header (the <soap:Body> root element's local name, set by the SOAP consumer) and dispatches to the method whose name — or [SoapOperation("...")] — matches. The XML body binds to the [FromBody] / single complex parameter via XmlSerializer, and the return value is XML-serialized into the response, which the SOAP consumer wraps in an envelope. A missing/unknown operation or an invocation exception throws, so the SOAP consumer returns a soap:Fault.

[Route("air")]
public class AirController : RedbController
{
    // Method name = SOAP operation; body binds from XML, reply serializes to XML.
    public Task<GetFaresResponse> GetFares([FromBody] GetFaresRequest req) => /* ... */;

    // Explicit operation name when it differs from the method name:
    [SoapOperation("HealthCheck")]
    public string Health() => "ok";
}

// Behind a Soap.Listen(...) consumer:
route.From(Soap.Listen("/svc/air").Host("0.0.0.0").Port(4090))
     .RedbSoapController<AirController>();

// Multiple controllers (qualified "Air.GetFares" disambiguates):
route.From(Soap.Listen("/svc").Host("0.0.0.0").Port(4090))
     .RedbSoapController(typeof(AirController), typeof(HotelController));

DTOs are ordinary XML-serializable types ([XmlRoot] matching the request/response element), and may be generated from a WSDL with dotnet-svcutil. No HTTP attributes required.

Use it behind a consumer in the default Payload data format. The dispatcher owns per-operation typing and the inner <soap:Body> XML, so it is not meant to be combined with Message (whole-envelope) or Pojo (single fixed request type) mode.

ControllerRegistry

Builds a route lookup table by scanning assemblies or registering individual controller types:

var registry = new ControllerRegistry();

// Scan entire assembly
int count = registry.RegisterAssembly(typeof(OrdersController).Assembly);

// Or register individual controllers
registry.RegisterController(typeof(OrdersController));
registry.RegisterController(typeof(UsersController));

// Resolve manually
var action = registry.Resolve(HttpMethodType.Get, "orders/42", out var routeParams);
// action.ControllerType = typeof(OrdersController)
// action.Method = GetOrder
// routeParams["id"] = "42"

Response Conventions

These are the replies of the five dispatchers (generic, HTTP, SignalR, gRPC; SOAP answers faults instead of error bodies). They end the exchange as an API endpoint does. The direct-invoke overloads are route steps and follow the bean rules below instead.

Scenario status.code Body
Method returns a value (T, Task<T>, ValueTask<T>) 200 Return value (JSON-serialized for HTTP/gRPC)
Method returns null, void, Task or ValueTask 204 — (the request body is not echoed)
Missing headers, or a value that does not bind 400 ControllerErrorResponse
No matching action 404 ControllerErrorResponse
Exception during invocation 500 ControllerErrorResponse

An action may answer by itself: write Exchange.Out (body, status, headers), call Exchange.Stop() and return null. The dispatcher keeps that reply as it is and only fills in a missing status.code and Content-Type.

// Error response model
public sealed class ControllerErrorResponse
{
    public string Error { get; init; }      // e.g. "NotFound", "BadRequest", "InternalError"
    public string Message { get; init; }    // Human-readable description
    public int StatusCode { get; init; }    // HTTP status code
}

DSL Extension Methods

All methods are on IRouteDefinition:

Method Dispatcher Headers Read
RedbController(registry) Generic route.path, route.method
RedbController<T>() Generic route.path, route.method
RedbController<T>(methodName) Direct invoke —
RedbController(registry, ctrlName, methodName) Direct invoke —
RedbController(registry, ctrlExpr, methodExpr) Dynamic Exchange-dependent
RedbHttpController(registry) HTTP redbHttp.Method, redbHttp.Path
RedbHttpController<T>() HTTP redbHttp.Method, redbHttp.Path
RedbSignalRController<T>() SignalR redbSignalR.Method
RedbSignalRController(types) SignalR redbSignalR.Method
RedbSignalRController(registry) SignalR redbSignalR.Method
RedbSoapController<T>() SOAP redbSoap.operation
RedbSoapController(types) SOAP redbSoap.operation
RedbSoapController(registry) SOAP redbSoap.operation
RedbGrpcController<T>() gRPC dispatch-method
RedbGrpcController(types) gRPC dispatch-method
RedbGrpcController(registry) gRPC dispatch-method

Direct invoke is a bean step

RedbController<T>(methodName), RedbController(registry, ctrlName, methodName) and RedbController(registry, ctrlExpr, methodExpr) call one method as a step in the middle of a route, the way the core's .Bean<TService>(...) and the bean: endpoint do (Camel's .bean(...)), with the controller conveniences on top: an instance per exchange, Context/Exchange set, and the binding attributes above.

Method returns Message after the step
a value (T, Task<T>, ValueTask<T>) the value is the body, status.code = 200
null, void, Task or ValueTask unchanged: the next step sees what this one received
throws the exchange fails with the action's own exception, so OnException(typeof(...)) matches it
// The audit step records and passes the order on untouched; the pricing step replaces the body.
route.From("direct://orders")
     .RedbController<AuditController>(nameof(AuditController.Record))     // void
     .RedbController<PricingController>(nameof(PricingController.Quote))  // returns a Quote
     .To("direct://billing");

Requirements

  • .NET 8.0 / 9.0 / 10.0
  • redb.Route (core) — no external dependencies
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on redb.Route.Controllers:

Package Downloads
redb.Route.Core

Bridge package connecting redb.Route ESB framework with redb.Core typed props storage. Provides RedbIdempotentRepository, typed access to IRedbService from route pipelines, and extension methods for redb.Core integration.

redb.Identity.Http

HTTP / HTTPS facade for redb.Identity — OIDC discovery, token, authorize, userinfo, introspect, revoke, JWKS, PAR, DCR, SCIM, /me and management endpoints.

redb.Identity.Management

Transport-neutral management and self-service controllers for redb.Identity. Thin adapters over the direct-vm://identity-manage-* routes, shared by every facade.

redb.Identity.Grpc

gRPC facade for redb.Identity — service-to-service surface: token, introspection, revocation, userinfo, discovery, JWKS.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.2.3 55 10/8/2026
4.2.2 253 10/5/2026
4.2.0 267 9/30/2026
4.1.1 277 9/25/2026
4.1.0 275 9/21/2026
4.0.1 283 9/18/2026
4.0.0 297 9/11/2026
3.7.2 294 8/26/2026
3.7.1 304 8/26/2026
3.6.0 237 8/13/2026
3.5.1 240 8/9/2026
3.5.0 256 8/6/2026
3.4.0 287 7/27/2026
3.3.3 303 7/16/2026
3.3.1 536 7/10/2026
3.3.0 177 7/8/2026
3.2.0 267 6/29/2026
3.1.0 289 6/6/2026
3.0.1 175 6/3/2026
Loading failed