Documentation Index Fetch the complete documentation index at: https://easyaf.dev/llms.txt
Use this file to discover all available pages before exploring further.
This guide covers all aspects of configuring SimpleMessageBus in your .NET applications, from basic setup to advanced scenarios.
Basic Configuration
Configure for ASP.NET Core
Configure SimpleMessageBus in your Program.cs file: using SimpleMessageBus . Publish . Azure . Extensions ;
using SimpleMessageBus . Dispatch . Azure . Extensions ;
var builder = WebApplication . CreateBuilder ( args );
// Configure publisher
builder . Services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . ConnectionString = builder . Configuration . GetConnectionString ( "AzureStorage" );
options . DefaultQueueName = "messages" ;
});
// Configure dispatcher
builder . Services . AddSimpleMessageBusAzureStorageDispatcher ( options =>
{
options . ConnectionString = builder . Configuration . GetConnectionString ( "AzureStorage" );
options . MaxConcurrentMessages = 32 ;
options . PollingInterval = TimeSpan . FromSeconds ( 5 );
});
// Register message handlers
builder . Services . AddScoped < IMessageHandler , OrderCreatedHandler >();
var app = builder . Build ();
app . Run ();
Configure for Console Applications
For console applications, use the generic host: using Microsoft . Extensions . Hosting ;
using Microsoft . Extensions . DependencyInjection ;
var builder = Host . CreateApplicationBuilder ( args );
// Configure SimpleMessageBus
builder . Services . AddSimpleMessageBusFileSystemPublisher ( options =>
{
options . RootPath = Path . Combine ( Directory . GetCurrentDirectory (), "messages" );
});
builder . Services . AddSimpleMessageBusFileSystemDispatcher ( options =>
{
options . RootPath = Path . Combine ( Directory . GetCurrentDirectory (), "messages" );
});
// Register handlers
builder . Services . AddScoped < IMessageHandler , OrderHandler >();
var host = builder . Build ();
await host . RunAsync ();
Provider-Specific Configuration
Azure Storage Queue
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . ConnectionString = "DefaultEndpointsProtocol=https;AccountName=..." ;
options . DefaultQueueName = "messages" ;
options . CreateQueuesAutomatically = true ;
});
services . AddSimpleMessageBusAzureStorageDispatcher ( options =>
{
options . ConnectionString = "DefaultEndpointsProtocol=https;AccountName=..." ;
options . DefaultQueueName = "messages" ;
options . PollingInterval = TimeSpan . FromSeconds ( 5 );
options . MaxConcurrentMessages = 32 ;
options . VisibilityTimeout = TimeSpan . FromMinutes ( 5 );
});
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . AccountName = "mystorageaccount" ;
// No connection string - uses managed identity
options . DefaultQueueName = "messages" ;
});
services . AddSingleton < IQueueNameResolver , CustomQueueNameResolver >();
public class CustomQueueNameResolver : IQueueNameResolver
{
public string ResolveQueueName < T >( T message ) where T : IMessage
{
return $" { typeof ( T ). Name . ToLowerInvariant ()} -queue" ;
}
}
Amazon SQS
services . AddSimpleMessageBusAmazonSQSPublisher ( options =>
{
options . Region = "us-east-1" ;
options . AccessKey = "AKIAIOSFODNN7EXAMPLE" ;
options . SecretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" ;
options . DefaultQueueName = "messages" ;
});
services . AddSimpleMessageBusAmazonSQSPublisher ( options =>
{
options . Region = "us-east-1" ;
options . UseInstanceProfile = true ; // Use attached IAM role
options . DefaultQueueName = "messages" ;
});
services . AddSimpleMessageBusAmazonSQSPublisher ( options =>
{
options . DefaultQueueName = "messages.fifo" ;
options . UseFifoQueues = true ;
options . MessageGroupId = "default" ;
options . ContentBasedDeduplication = true ;
});
File System
services . AddSimpleMessageBusFileSystemPublisher ( options =>
{
options . RootPath = @"C:\MessageQueue" ;
options . CreateDirectoriesAutomatically = true ;
});
services . AddSimpleMessageBusFileSystemDispatcher ( options =>
{
options . RootPath = @"C:\MessageQueue" ;
options . PollingInterval = TimeSpan . FromSeconds ( 1 );
options . ProcessedDirectory = "processed" ;
options . ErrorDirectory = "errors" ;
});
Azure Functions Integration
[ FunctionName ( "ProcessMessage" )]
public async Task ProcessFileMessage (
[ SimpleMessageBusFileTrigger ( "messages" )] MessageEnvelope envelope ,
ILogger log )
{
await _dispatcher . Dispatch ( envelope );
}
IndexedDB (Blazor WebAssembly)
// Program.cs in Blazor WebAssembly
builder . Services . AddSimpleMessageBusIndexedDbPublisher ( options =>
{
options . DatabaseName = "MessageBusDB" ;
options . DatabaseVersion = 1 ;
});
builder . Services . AddSimpleMessageBusIndexedDbDispatcher ( options =>
{
options . DatabaseName = "MessageBusDB" ;
options . PollingInterval = TimeSpan . FromSeconds ( 2 );
});
Environment-Based Configuration
By Environment
With Feature Flags
Configure different providers for different environments: var builder = WebApplication . CreateBuilder ( args );
if ( builder . Environment . IsDevelopment ())
{
// Use file system in development
builder . Services . AddSimpleMessageBusFileSystemPublisher ( options =>
{
options . RootPath = Path . Combine ( Directory . GetCurrentDirectory (), "dev-messages" );
});
builder . Services . AddSimpleMessageBusFileSystemDispatcher ( options =>
{
options . RootPath = Path . Combine ( Directory . GetCurrentDirectory (), "dev-messages" );
options . PollingInterval = TimeSpan . FromSeconds ( 1 );
});
}
else if ( builder . Environment . IsStaging ())
{
// Use Azure Storage in staging
builder . Services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . ConnectionString = builder . Configuration . GetConnectionString ( "StagingStorage" );
options . DefaultQueueName = "staging-messages" ;
});
builder . Services . AddSimpleMessageBusAzureStorageDispatcher ( options =>
{
options . ConnectionString = builder . Configuration . GetConnectionString ( "StagingStorage" );
options . DefaultQueueName = "staging-messages" ;
});
}
else // Production
{
// Use Amazon SQS in production
builder . Services . AddSimpleMessageBusAmazonSQSPublisher ( options =>
{
options . Region = builder . Configuration [ "AWS:Region" ];
options . UseInstanceProfile = true ;
options . DefaultQueueName = "production-messages" ;
});
builder . Services . AddSimpleMessageBusAmazonSQSDispatcher ( options =>
{
options . Region = builder . Configuration [ "AWS:Region" ];
options . UseInstanceProfile = true ;
options . DefaultQueueName = "production-messages" ;
});
}
Use feature flags to control provider selection: var useAmazonSQS = builder . Configuration . GetValue < bool >( "Features:UseAmazonSQS" );
var useHighThroughput = builder . Configuration . GetValue < bool >( "Features:HighThroughput" );
if ( useAmazonSQS )
{
builder . Services . AddSimpleMessageBusAmazonSQSPublisher ( options =>
{
builder . Configuration . GetSection ( "AmazonSQS" ). Bind ( options );
});
}
else
{
builder . Services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
builder . Configuration . GetSection ( "AzureStorage" ). Bind ( options );
});
}
// Adjust concurrency based on feature flag
builder . Services . Configure < DispatcherOptions >( options =>
{
options . MaxConcurrentMessages = useHighThroughput ? 64 : 16 ;
});
Message Handler Registration
Manual Registration
Assembly Scanning
Conditional Registration
Register individual handlers explicitly: // Register individual handlers
services . AddScoped < IMessageHandler , OrderCreatedHandler >();
services . AddScoped < IMessageHandler , PaymentProcessedHandler >();
services . AddScoped < IMessageHandler , InventoryReservedHandler >();
Best for : Small projects with few handlers.Automatically discover and register handlers: // Register all handlers from current assembly
services . Scan ( scan => scan
. FromAssemblyOf < OrderCreatedHandler >()
. AddClasses ( classes => classes . AssignableTo < IMessageHandler >())
. As < IMessageHandler >()
. WithScopedLifetime ());
// Register handlers from multiple assemblies
services . Scan ( scan => scan
. FromAssemblies (
Assembly . GetExecutingAssembly (),
Assembly . GetAssembly ( typeof ( ExternalHandler )))
. AddClasses ( classes => classes . AssignableTo < IMessageHandler >())
. As < IMessageHandler >()
. WithScopedLifetime ());
Best for : Large projects with many handlers.Register handlers based on configuration: // Register handlers based on configuration
if ( builder . Configuration . GetValue < bool >( "Features:OrderProcessing" ))
{
services . AddScoped < IMessageHandler , OrderCreatedHandler >();
services . AddScoped < IMessageHandler , OrderCancelledHandler >();
}
if ( builder . Configuration . GetValue < bool >( "Features:PaymentProcessing" ))
{
services . AddScoped < IMessageHandler , PaymentProcessedHandler >();
services . AddScoped < IMessageHandler , PaymentFailedHandler >();
}
Best for : Feature flag-based deployments.
Advanced Configuration
Multiple Providers
Use different providers for different message types:
// Configure multiple publishers with names
services . AddSimpleMessageBusAzureStoragePublisher ( "orders" , options =>
{
options . ConnectionString = azureConnectionString ;
options . DefaultQueueName = "orders" ;
});
services . AddSimpleMessageBusAmazonSQSPublisher ( "payments" , options =>
{
options . Region = "us-east-1" ;
options . UseInstanceProfile = true ;
options . DefaultQueueName = "payments" ;
});
// Use named publishers
public class OrderService
{
private readonly IMessagePublisher _orderPublisher ;
private readonly IMessagePublisher _paymentPublisher ;
public OrderService (
[ FromKeyedServices ( "orders" )] IMessagePublisher orderPublisher ,
[ FromKeyedServices ( "payments" )] IMessagePublisher paymentPublisher )
{
_orderPublisher = orderPublisher ;
_paymentPublisher = paymentPublisher ;
}
public async Task ProcessOrderAsync ( Order order )
{
await _orderPublisher . PublishAsync ( new OrderCreatedMessage { ... });
await _paymentPublisher . PublishAsync ( new ProcessPaymentMessage { ... });
}
}
Custom Dispatcher Configuration
Configure message dispatching behavior:
// Parallel dispatcher (default)
services . AddSimpleMessageBusParallelDispatcher ( options =>
{
options . MaxConcurrency = Environment . ProcessorCount * 2 ;
options . BatchSize = 10 ;
});
// Ordered dispatcher
services . AddSimpleMessageBusOrderedDispatcher ();
// Custom dispatcher
services . AddScoped < IMessageDispatcher , CustomMessageDispatcher >();
Serialization Configuration
Customize JSON serialization:
services . Configure < JsonSerializerOptions >( options =>
{
options . PropertyNamingPolicy = JsonNamingPolicy . CamelCase ;
options . WriteIndented = true ;
options . Converters . Add ( new JsonStringEnumConverter ());
});
// Or configure per provider
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . SerializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy . CamelCase
};
});
Configuration Best Practices
1. Use Configuration Sections
Organize configuration in appsettings.json:
{
"SimpleMessageBus" : {
"Azure" : {
"ConnectionString" : "DefaultEndpointsProtocol=https;..." ,
"DefaultQueueName" : "messages" ,
"MaxConcurrentMessages" : 32 ,
"PollingInterval" : "00:00:05"
},
"Amazon" : {
"Region" : "us-east-1" ,
"DefaultQueueName" : "messages" ,
"UseFifoQueues" : false ,
"WaitTimeSeconds" : 20
}
}
}
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
builder . Configuration . GetSection ( "SimpleMessageBus:Azure" ). Bind ( options );
});
2. Environment-Specific Settings
Use different configuration files per environment:
// appsettings.Development.json
{
"SimpleMessageBus" : {
"Provider" : "FileSystem" ,
"FileSystem" : {
"RootPath" : "./dev-messages" ,
"PollingInterval" : "00:00:01"
}
}
}
// appsettings.Production.json
{
"SimpleMessageBus" : {
"Provider" : "AmazonSQS" ,
"Amazon" : {
"Region" : "us-east-1" ,
"UseInstanceProfile" : true ,
"WaitTimeSeconds" : 20
}
}
}
3. Secure Configuration
Store sensitive values in Azure Key Vault or AWS Secrets Manager:
// Azure Key Vault
builder . Configuration . AddAzureKeyVault (
vaultUri : "https://myvault.vault.azure.net/" ,
credential : new DefaultAzureCredential ());
// AWS Secrets Manager
builder . Configuration . AddSecretsManager ( region : RegionEndpoint . USEast1 );
// Use in configuration
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . ConnectionString = builder . Configuration [ "SimpleMessageBus:ConnectionString" ];
});
4. Configuration Validation
Validate configuration at startup:
services . Configure < AzureStorageOptions >(
builder . Configuration . GetSection ( "SimpleMessageBus:Azure" ));
services . AddOptions < AzureStorageOptions >()
. Configure ( builder . Configuration . GetSection ( "SimpleMessageBus:Azure" ))
. ValidateDataAnnotations ()
. ValidateOnStart ();
public class AzureStorageOptions
{
[ Required ]
public string ConnectionString { get ; set ; }
[ Required ]
[ RegularExpression ( @"^[a-z0-9-]+$" )]
public string DefaultQueueName { get ; set ; }
[ Range ( 1 , 32 )]
public int MaxConcurrentMessages { get ; set ; } = 16 ;
}
Monitoring and Observability Configuration
Logging
Configure structured logging:
builder . Services . AddLogging ( logging =>
{
logging . ClearProviders ();
logging . AddConsole ();
logging . AddApplicationInsights ();
// Filter SimpleMessageBus logs
logging . AddFilter ( "SimpleMessageBus" , LogLevel . Information );
});
Metrics
Configure metrics collection:
builder . Services . AddMetrics ();
// Custom metrics
services . AddSingleton < IMetrics >( provider =>
{
var factory = provider . GetRequiredService < IMeterFactory >();
return factory . Create ( "SimpleMessageBus.Application" );
});
Health Checks
Add health checks for message bus components:
services . AddHealthChecks ()
. AddCheck < MessageBusHealthCheck >( "messagebus" )
. AddAzureQueueStorage ( connectionString , "messages" )
. AddSqs ( options => { ... });
Testing Configuration
Integration Tests
Configure for integration testing:
public class TestStartup
{
public void ConfigureServices ( IServiceCollection services )
{
// Use in-memory provider for tests
services . AddSimpleMessageBusInMemoryProvider ();
// Or use test containers
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
options . ConnectionString = "UseDevelopmentStorage=true" ;
});
}
}
Unit Tests
Mock configuration for unit tests:
[ Test ]
public void Configure_WithValidOptions_RegistersServices ()
{
var services = new ServiceCollection ();
var configuration = new ConfigurationBuilder ()
. AddInMemoryCollection ( new Dictionary < string , string >
{
[ "ConnectionString" ] = "UseDevelopmentStorage=true" ,
[ "DefaultQueueName" ] = "test-queue"
})
. Build ();
services . AddSimpleMessageBusAzureStoragePublisher ( options =>
{
configuration . Bind ( options );
});
var provider = services . BuildServiceProvider ();
var publisher = provider . GetService < IMessagePublisher >();
Assert . That ( publisher , Is . Not . Null );
}
Troubleshooting Configuration Issues
Problem : Authentication failures or connection errorsSolutions :
Verify connection string format
Check account credentials
Ensure network connectivity
Validate queue/storage account exists
// Test connection at startup
services . AddHealthChecks ()
. AddAzureQueueStorage ( connectionString );
Handler Registration Problems
Problem : Handlers not receiving messagesSolutions :
Verify handler implements IMessageHandler
Check GetHandledMessageTypes() returns correct types
Ensure handler is registered in DI container
Verify message type matches exactly
// Debug handler registration
var handlers = serviceProvider . GetServices < IMessageHandler >();
foreach ( var handler in handlers )
{
var types = handler . GetHandledMessageTypes ();
Console . WriteLine ( $"Handler { handler . GetType (). Name } handles: { string . Join ( ", " , types . Select ( t => t . Name ))} " );
}
Next Steps
Testing Guide Learn how to test your configuration
Error Handling Implement robust error handling
Performance Guide Optimize for production workloads
Provider Guides Deep dive into specific providers