Start here

Quickstart

From zero to a running Relay service: install the package, define a command, and let the pipeline do the rest.

1. Install

Relay targets .NET 10 (net10.0). Add the meta package to your web project:

dotnet add package Nuvora.Nexus.Relay

Capabilities are split into focused packages (Nuvora.Nexus.Relay.EventStore.EfCore, .Messaging.RabbitMq, .Tenancy, …) that you add as you adopt them — see the package reference.

2. Define a message and its handler

A command is an immutable record; its handler is the single place its behavior lives. HTTP attributes generate the endpoint for you:

[RelayHttpPost("/products")]
[RelayHttpTag("Catalog")]
[AllowAnonymous]
public sealed record CreateProductCommand(
    string Name, string Category, decimal Price) : ICommand<Product>;

public sealed class CreateProductCommandHandler(ProductCatalog catalog)
    : ICommandHandler<CreateProductCommand, Product>
{
    public Task<Product> Handle(CreateProductCommand command, CancellationToken ct)
    {
        var product = new Product(
            Id: $"p-{Guid.NewGuid():N}",
            Name: command.Name.Trim(),
            Category: command.Category.Trim().ToLowerInvariant(),
            Price: command.Price);

        return Task.FromResult(catalog.Save(product));
    }
}

Validation is a class implementing ICommandValidator<,> next to the command; the pipeline runs it automatically.

3. Wire the host

var builder = WebApplication.CreateBuilder(args);

// One scan: every handler, validator and behavior in the assembly.
builder.Services.AddRelay(typeof(CreateProductCommand).Assembly);

var app = builder.Build();

app.UseRelayExceptionHandling();   // ProblemDetails + correlation ids
app.UseRouting();
app.UseEndpoints(e => e.MapRelayEndpoints()); // endpoints from [RelayHttp*]

app.Run();

Run it, and POST /products exists — validated, logged, wrapped in a transaction, and refused at startup if its authorization posture were missing.

4. Keep going