Skip to content

DashboardConfiguration

blehnen edited this page Nov 10, 2026 · 7 revisions

Dashboard Configuration

DashboardOptions
Property Type Default Description
EnableSwagger bool true Enables Swagger/OpenAPI UI at /swagger
AuthorizationPolicy string null ASP.NET Core authorization policy name applied to all dashboard endpoints
ApiKey string null When set, all endpoints require an X-Api-Key header matching this value
EnableConsumerTracking bool true Enable consumer registration and heartbeat tracking
ConsumerHeartbeatIntervalSeconds int 30 Heartbeat interval returned to consumers. It also controls the pruning frequency
ConsumerStaleThresholdSeconds int 90 Seconds without heartbeat before a consumer is pruned
ReadOnly bool false When true, disables all write operations (requeue, delete, edit)
EnableCors bool false Enable CORS for cross-origin API access
CorsOrigins string[] empty Allowed origins when CORS is enabled
AssemblyPaths string[] empty Additional directories for message type resolution (used for body display)
Adding connections

Use AddConnection<TTransportInit>() to register a transport connection. Each connection requires a connection string and can contain multiple queues.

builder.Services.AddDotNetWorkQueueDashboard(options =>
{
    options.AddConnection<SqlServerMessageQueueInit>(
        "Server=myserver;Database=mydb;Trusted_Connection=true;",
        conn =>
        {
            conn.DisplayName = "Production SQL Server";
            conn.AddQueue("OrderQueue");
            conn.AddQueue("NotificationQueue");
        });
});

The transport init types are:

Transport Init Type
SQL Server SqlServerMessageQueueInit
PostgreSQL PostgreSqlMessageQueueInit
SQLite SqLiteMessageQueueInit
LiteDb LiteDbMessageQueueInit
Redis RedisQueueInit
Memory MemoryMessageQueueInit
Message interceptors

If your queues use message interceptors (compression or encryption), you must register the same interceptors on the dashboard queue so that it can decode message bodies.

conn.AddQueue("EncryptedQueue", container =>
{
    container.Register(() => new AesMessageInterceptorConfiguration(key), LifeStyles.Singleton);
    container.RegisterCollection<IMessageInterceptor>(new[]
    {
        typeof(GZipMessageInterceptor),
        typeof(AesMessageInterceptor)
    });
});

key is the same 32-byte AES key that the producers and consumers use.

Without matching interceptors, message body inspection returns encoded/encrypted data.

Interceptor profiles

You can register reusable interceptor configurations by name and reference them per-queue:

builder.Services.AddDotNetWorkQueueDashboard(options =>
{
    options.AddInterceptorProfile("compressed", container =>
    {
        container.RegisterCollection<IMessageInterceptor>(new[] { typeof(GZipMessageInterceptor) });
    });

    options.AddConnection<SqlServerMessageQueueInit>(connectionString, conn =>
    {
        conn.DisplayName = "Production";
        conn.AddQueueWithProfile("CompressedQueue", "compressed");
    });
});
JSON-based interceptor configuration

You can configure the built-in GZip and AES interceptors entirely from appsettings.json, without code. The Interceptors section applies to every queue in every connection:

{
  "Dashboard": {
    "Interceptors": {
      "GZip": {
        "Enabled": true,
        "MinimumSize": 150
      },
      "Aes": {
        "Enabled": true,
        "Key": "BASE64_ENCODED_32_BYTE_KEY"
      }
    },
    "Connections": [
      {
        "Transport": "SqlServer",
        "ConnectionString": "Server=myserver;Database=mydb;Trusted_Connection=true;",
        "DisplayName": "Production",
        "Queues": [ "EncryptedQueue" ]
      }
    ]
  }
}

The Interceptors:TripleDes section was removed in 0.16.0. If it is still present, the dashboard throws an InvalidOperationException at startup. See the Migration Guide.

Security warning: Do not store Key values in appsettings.json files committed to source control. Use .NET User Secrets for development and a secrets manager for production.

The priority order for interceptor configuration is: inline delegate > named profile > JSON options.

Authorization

To restrict access to dashboard endpoints, set AuthorizationPolicy to the name of a registered ASP.NET Core authorization policy:

builder.Services.AddAuthorization(auth =>
{
    auth.AddPolicy("DashboardPolicy", policy =>
        policy.RequireRole("Admin"));
});

builder.Services.AddDotNetWorkQueueDashboard(options =>
{
    options.AuthorizationPolicy = "DashboardPolicy";
});

When AuthorizationPolicy is set, all dashboard controllers require the specified policy. When it is null (the default), the endpoints are open with no authorization.

API key authentication

To secure endpoints with an API key, set the ApiKey option:

builder.Services.AddDotNetWorkQueueDashboard(options =>
{
    options.ApiKey = "my-secret-key";
});

Security note: Never hardcode the API key in source code. Read it from an environment variable, .NET User Secrets, or a vault. Rotate the key periodically.

All requests must then include the X-Api-Key header with the matching value. When Swagger is enabled and an API key is configured, the Swagger UI includes an API key input field.

Consumer tracking

When EnableConsumerTracking is true (the default), consumers can register with the dashboard and send periodic heartbeats. The dashboard tracks active consumers per queue and prunes any that miss heartbeats.

Use the Dashboard Client package (DashboardConsumerClient) for automatic registration and heartbeat management.

Host maintenance

The dashboard can run queue maintenance monitors (heartbeat reset, expiration cleanup, error cleanup) instead of your consumers. Enable it per queue:

conn.AddQueue("OrderQueue", hostMaintenance: true);

See Maintenance Mode for details on configuring consumers to use external maintenance.

Error handling

The dashboard includes a global exception filter that maps exceptions to HTTP status codes:

Exception HTTP Status
InvalidOperationException 404 Not Found
NotSupportedException 501 Not Implemented
ObjectDisposedException 503 Service Unavailable

Clone this wiki locally