MqttControllerFramework 1.0.0
dotnet add package MqttControllerFramework --version 1.0.0
NuGet\Install-Package MqttControllerFramework -Version 1.0.0
<PackageReference Include="MqttControllerFramework" Version="1.0.0" />
<PackageVersion Include="MqttControllerFramework" Version="1.0.0" />
<PackageReference Include="MqttControllerFramework" />
paket add MqttControllerFramework --version 1.0.0
#r "nuget: MqttControllerFramework, 1.0.0"
#:package MqttControllerFramework@1.0.0
#addin nuget:?package=MqttControllerFramework&version=1.0.0
#tool nuget:?package=MqttControllerFramework&version=1.0.0
MqttControllerFramework
An ASP.NET Core–style source-generated MQTT controller framework for .NET, built on top of MQTTnet 5. Define topic handlers with attributes; the compile-time source generator handles routing, dispatch, and DI wiring — zero reflection at runtime.
Features
| Feature | Description |
|---|---|
| Attribute-driven routing | [MqttController] + [MqttTopic("sensors/+/temperature")] |
| Source-generated dispatch | Routing, dispatcher, and registration code generated at compile time |
| Compile-time route validation | MQTT001/MQTT002 diagnostics flag duplicate and ambiguous topic patterns at build time |
| Middleware pipeline | ASP.NET Core–style IMqttMiddleware with per-message DI scope |
| Authentication | IMqttAuthenticationProvider — username/password with lockout support |
| Authorization | IMqttAuthorizationProvider — publish + subscribe, QoS and retain constraints |
| Connection validation | IMqttConnectionValidator — pre-auth ClientId/IP checks, session-item seeding, auth bypass |
| Token-bucket rate limiting | [TokenBucketRateLimit(capacity, refillRate, intervalMs)] per-route |
| Broker stats | IMqttBrokerStatsService — message counters, byte throughput, per-topic summaries |
| TLS hot-swap | Reload PEM / PKCS#12 certificates at runtime without restart |
| Server-side publish | IMqttClientActionService — push messages from broker to topics |
| Custom payload parsers | IMqttPayloadParser<T> — binary, MessagePack, Protobuf, etc. |
| Pluggable retain storage | IRetainStorage — swap the built-in JSON file backend for a database, Redis, or blob store |
| Lifecycle events | Connected, disconnected, subscribed, unsubscribed |
| Multi-target | net8.0 and net10.0 |
Installation
dotnet add package MqttControllerFramework
Or add directly to your project file:
<PackageReference Include="MqttControllerFramework" Version="1.0.0" />
Quick Start
1. Register the broker
// Program.cs
builder.Services
.AddMqttServer(builder.Configuration.GetSection("MqttSettings"))
.WithControllers<GeneratedMqttControllerRegistration>()
.WithAuthentication<MyAuthProvider>();
var app = builder.Build();
app.Run();
2. Configure
// appsettings.json
{
"MqttSettings": {
"EnableNonSsl": true,
"NonSslPort": 1883
}
}
3. Write a controller
using MqttControllerFramework.Attributes;
[MqttController]
public class SensorsController
{
[MqttTopic("sensors/+/temperature")]
public async Task OnTemperature(
[FromMqttTopic(1)] string deviceId,
TemperaturePayload payload,
CancellationToken ct)
{
Console.WriteLine($"Device {deviceId}: {payload.Value}°C");
}
}
public record TemperaturePayload(double Value, string Unit);
4. Implement authentication
public class MyAuthProvider : IMqttAuthenticationProvider
{
public ValueTask<MqttAuthenticationResult> AuthenticateAsync(
string username, string password, CancellationToken ct)
{
var ok = username == "device" && password == "secret";
return ValueTask.FromResult(
ok ? MqttAuthenticationResult.Authenticated()
: MqttAuthenticationResult.Failed("Invalid credentials"));
}
}
The source generator produces
GeneratedMqttControllerRegistrationin the<YourAssembly>.Mqtt.Generatednamespace at build time. Add ausingfor that namespace, or use a global using, to reference the class.
Full Builder API
builder.Services
.AddMqttServer(configuration) // registers the broker, reads MqttSettings section
.WithControllers<TRegistration>() // source-generated registration class
.WithAuthentication<TProvider>() // IMqttAuthenticationProvider (required)
.WithAuthorization<TProvider>() // IMqttAuthorizationProvider (optional)
.WithConnectionValidator<TValidator>() // IMqttConnectionValidator — pre-auth hook
.WithNetworkTracker<TTracker>() // replace built-in in-memory tracker
.WithRetainStorage<TStorage>() // IRetainStorage — custom retain message backend
.UseMiddleware<TMiddleware>() // IMqttMiddleware (ordered, chainable)
.WithRateLimiting() // enable token-bucket rate limiting
.OnClientConnected<THandler>() // IMqttClientConnectedEvent
.OnClientDisconnected<THandler>() // IMqttClientDisconnectedEvent
.OnClientSubscribedTopic<THandler>() // IMqttClientSubscribedTopicEvent
.OnClientUnsubscribedTopic<THandler>(); // IMqttClientUnsubscribedTopicEvent
Middleware Example (multi-tenancy)
SessionItems is populated once during connection validation and lives for the lifetime of the TCP connection — ideal for tenant, user, or role resolution:
// Connection validator — runs once per connection
public class ConnectionValidator : IMqttConnectionValidator
{
public async ValueTask<MqttConnectionValidationResult> ValidateAsync(
ValidatingConnectionEventArgs ctx, CancellationToken ct)
{
ctx.SessionItems["tenantId"] = await ResolveTenantAsync(ctx.UserName);
return MqttConnectionValidationResult.Accept();
}
}
// Middleware — runs for every message
public class TenantMiddleware(ITenantContext tenant) : IMqttMiddleware
{
public Task InvokeAsync(MqttMessageContext ctx, MqttRequestDelegate next)
{
if (ctx.SessionItems["tenantId"] is string tid)
tenant.SetTenant(tid);
return next(ctx);
}
}
Register both:
builder.Services
.AddMqttServer(configuration)
.WithControllers<GeneratedMqttControllerRegistration>()
.WithConnectionValidator<ConnectionValidator>()
.UseMiddleware<TenantMiddleware>()
.WithAuthentication<MyAuthProvider>();
Rate Limiting
[MqttController]
public class TelemetryController
{
// Allow burst of 10, refill 5 tokens every 1 second, consume 1 per message
[MqttTopic("telemetry/+/data")]
[TokenBucketRateLimit(capacity: 10, refillRate: 5, refillIntervalMs: 1000)]
public Task OnData([FromMqttTopic(1)] string deviceId, SensorData payload) { ... }
}
Enable rate limiting in the builder:
.WithRateLimiting()
TLS
"MqttSettings": {
"EnableSsl": true,
"SslPort": 8883,
"PkcsPath": "/etc/certs/broker.pfx",
"PkcsPassword": "changeme"
}
PEM + separate key file:
"MqttSettings": {
"EnableSsl": true,
"SslPort": 8883,
"PkcsPath": "/etc/certs/broker.crt",
"PkcsKeyPath": "/etc/certs/broker.key"
}
Documentation
| Topic | Page |
|---|---|
| Controllers & routing | docs/wiki/Controllers-and-Routing.md |
| Middleware pipeline | docs/wiki/Middleware.md |
| Authentication | docs/wiki/Authentication.md |
| Authorization | docs/wiki/Authorization.md |
| Connection validation | docs/wiki/Connection-Validation.md |
| Rate limiting | docs/wiki/Rate-Limiting.md |
| TLS & certificates | docs/wiki/TLS-and-Security.md |
| Retained messages | docs/wiki/Retained-Messages.md |
| Lifecycle events | docs/wiki/Events.md |
| Server-side publish | docs/wiki/Server-Actions.md |
| Broker statistics | docs/wiki/Broker-Stats.md |
| Performance | docs/wiki/Performance.md |
| Configuration reference | docs/wiki/Configuration-Reference.md |
License
MIT © IoT Viet Solution
| Product | Versions 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 was computed. 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. |
-
net10.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- MQTTnet (>= 5.1.0.1559)
- MQTTnet.AspNetCore (>= 5.1.0.1559)
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- MQTTnet (>= 5.1.0.1559)
- MQTTnet.AspNetCore (>= 5.1.0.1559)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 33 | 6/6/2026 |
| 1.0.0-alpha.4 | 33 | 6/6/2026 |
| 1.0.0-alpha.2 | 31 | 6/6/2026 |
| 1.0.0-alpha.1 | 34 | 6/6/2026 |