Getting Started with .NET Aspire
Provision KubeMQ in an Aspire AppHost and send your first message from a service project in minutes.
The KubeMQ .NET Aspire integration ships two NuGet packages that follow the standard Aspire two-package model: KubeMQ.Aspire.Hosting provisions a KubeMQ container as a resource in your AppHost, and KubeMQ.Aspire.Client wires an IKubeMQClient into a service project with health checks, OpenTelemetry, and keyed dependency injection. This guide takes you from an empty Aspire solution to publishing your first event and queue message.
Setup walkthrough
Prerequisites
You need the following installed before you begin:
| Requirement | Version |
|---|---|
| .NET SDK | 8.0 or 9.0 |
| .NET Aspire workload | 9.0+ |
| Docker | Running (for local container provisioning) |
| KubeMQ license key | Set via WithLicenseKey() |
Aspire provisions the KubeMQ broker as a local Docker container, so Docker must be running. The license key is supplied at deploy time as a secret parameter — you will add it in the AppHost step.
Install the Packages
Add the hosting package to your AppHost project:
dotnet add package KubeMQ.Aspire.HostingAdd the client package to each service project that talks to KubeMQ:
dotnet add package KubeMQ.Aspire.ClientThese packages build on Aspire.Hosting 9.0.0 and the KubeMQ.SDK.CSharp 3.0.1 client. If your solution uses central package management (Directory.Packages.props), pin those versions there.
Configure the AppHost
In the AppHost Program.cs, declare the license key as a secret parameter, provision the broker, and reference it from your service project. The WaitFor call ensures the service does not start until the broker is healthy.
var builder = DistributedApplication.CreateBuilder(args);
var kubemqKey = builder.AddParameter("kubemq-key", secret: true);
var messaging = builder.AddKubeMQ("messaging")
.WithLicenseKey(kubemqKey)
.WithDataVolume();
builder.AddProject<Projects.KubeMQ_Aspire_Sample_WebApi>("webapi")
.WithReference(messaging)
.WaitFor(messaging);
builder.Build().Run();AddKubeMQ("messaging") names the resource messaging — remember this name, because the service project uses it to resolve the connection. WithLicenseKey sets the KUBEMQ_TOKEN environment variable on the container from the secret parameter, and WithDataVolume binds a persistent volume to /store so messages survive container restarts.
The kubemq-key parameter value is read from configuration. For local development, set it once with dotnet user-secrets set Parameters:kubemq-key <your-license-key> in the AppHost project, or add it to appsettings.json under the Parameters section.
What AddKubeMQ Does
Behind the scenes, AddKubeMQ registers a container resource and configures it for you:
- Pulls the
europe-docker.pkg.dev/kubemq/images/kubemq:2.5.0image. - Exposes three endpoints — gRPC on target port
50000, REST on9090, and the Dashboard on8080. - Uses a persistent container lifetime (
ContainerLifetime.Persistent), so the container — and the data volume bound at/store— survives AppHost restarts.
This means the broker keeps running between debug sessions and your queued messages are not lost when you stop and restart the AppHost.
Configure the Service Project
In your service project Program.cs, register the KubeMQ client. The connection name passed to AddKubeMQClient must match the resource name from the AppHost (messaging). Aspire injects the host:port connection string automatically — you never hardcode an address.
var builder = WebApplication.CreateBuilder(args);
builder.AddKubeMQClient("messaging");
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();AddKubeMQClient registers an IKubeMQClient singleton, binds settings from the Aspire:KubeMQ:Client configuration section, and enables health checks (tagged ready and live), OpenTelemetry tracing (AddSource("KubeMQ.Sdk")), and metrics (AddMeter("KubeMQ.Sdk")) by default.
For multiple KubeMQ instances in one service, use AddKeyedKubeMQClient("name") for each connection and resolve them with [FromKeyedServices("name")]. See the Multiple KubeMQ Instances guide for details.
Send Your First Message
Inject IKubeMQClient into a controller and publish an event. Events are fire-and-forget — no response is expected. This controller builds an EventMessage on the events.example channel and calls SendEventAsync.
using System.Text;
using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Events;
using Microsoft.AspNetCore.Mvc;
namespace KubeMQ.Aspire.Sample.WebApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public sealed class EventsController : ControllerBase
{
private readonly IKubeMQClient _client;
public EventsController(IKubeMQClient client) => _client = client;
[HttpPost]
public async Task<IActionResult> PublishEvent([FromBody] string body)
{
var message = new EventMessage
{
Channel = "events.example",
Body = Encoding.UTF8.GetBytes(body),
Tags = new Dictionary<string, string> { ["source"] = "aspire-sample" },
};
await _client.SendEventAsync(message);
return Ok(new { Status = "published" });
}
}POST a JSON string body to /api/events and the message is published to the events.example channel.
Try a Queue (Send and Receive)
Events are one pattern; queues are another. Queue messages are persisted and consumed at-least-once, which makes them a good fit for work distribution. The same IKubeMQClient sends with SendQueueMessageAsync and pulls with ReceiveQueueMessagesAsync. The poll request below requests up to 5 messages, waits up to 5 seconds, and auto-acknowledges on receipt.
using System.Text;
using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Queues;
using Microsoft.AspNetCore.Mvc;
namespace KubeMQ.Aspire.Sample.WebApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public sealed class QueuesController : ControllerBase
{
private readonly IKubeMQClient _client;
public QueuesController(IKubeMQClient client) => _client = client;
[HttpPost]
public async Task<IActionResult> SendMessage([FromBody] string body)
{
var message = new QueueMessage
{
Channel = "queues.example",
Body = Encoding.UTF8.GetBytes(body),
};
var result = await _client.SendQueueMessageAsync(message);
return Ok(new { result.MessageId, result.IsError, result.Error });
}
[HttpGet]
public async Task<IActionResult> ReceiveMessages()
{
var request = new QueuePollRequest
{
Channel = "queues.example",
MaxMessages = 5,
WaitTimeoutSeconds = 5,
AutoAck = true,
};
var response = await _client.ReceiveQueueMessagesAsync(request);
var messages = response.Messages.Select(m => new
{
m.MessageId,
Body = Encoding.UTF8.GetString(m.Body.Span),
}).ToList();
return Ok(new { Count = messages.Count, Messages = messages });
}
}POST to /api/queues to enqueue a message, then GET /api/queues to drain up to five messages from the queues.example queue.
Run It
Start the whole distributed application from the AppHost project:
dotnet runAspire launches the dashboard in your browser. There you can confirm that the messaging container and the webapi resource are running and healthy. The sample service project calls MapDefaultEndpoints in its ServiceDefaults, which maps two health endpoints:
| Endpoint | Reports |
|---|---|
/health | Checks tagged ready (the broker connection is ready) |
/alive | Checks tagged live (the process is live) |
A green health indicator on webapi means the KubeMQ readiness check passed and the client is connected to the broker.
Worker-Style Services
Not every service is a web app. In a background worker or console service, use Host.CreateApplicationBuilder(args) instead of WebApplication.CreateBuilder(args). The client registration is identical — resolve IKubeMQClient from the host and call ConnectAsync before you publish or subscribe.
using System.Text;
using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Events;
var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults();
builder.AddKubeMQClient("messaging");
var host = builder.Build();
var client = host.Services.GetRequiredService<IKubeMQClient>();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
await client.ConnectAsync();
await client.SendEventAsync(new EventMessage
{
Channel = "events.fanout",
Body = Encoding.UTF8.GetBytes("Hello from a worker"),
});
await host.RunAsync();Next Steps
Pub/Sub
Publish and subscribe to events with IKubeMQClient — fan-out, ordering, and subscription patterns.
Queues
At-least-once queue messaging — send, poll, acknowledge, and tune QueuePollRequest.
Configuration & TLS
Settings, keyed clients, health checks, OpenTelemetry, and securing the connection with TLS.
Was this page helpful?