### Install NHibernate Unit Testing NuGet Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the NuGet package required for NHibernate unit testing. This package provides tools for mocking IQueryable repositories. ```shell dotnet add package Luxoft.Bss.Platform.NHibernate.UnitTesting ``` -------------------------------- ### Add API Documentation Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the platform API documentation NuGet package using the dotnet CLI. ```shell dotnet add package Luxoft.Bss.Platform.Api.Documentation ``` -------------------------------- ### Add Platform Logging Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the platform logging NuGet package using the dotnet CLI. ```shell dotnet add package Luxoft.Bss.Platform.Logging ``` -------------------------------- ### Install RabbitMQ Consumer Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Use this command to add the RabbitMQ consumer package to your .NET project. ```shell dotnet add package Luxoft.Bss.Platform.RabbitMq.Consumer ``` -------------------------------- ### Add Events Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the platform events NuGet package using the dotnet CLI. ```shell dotnet add package Luxoft.Bss.Platform.Events ``` -------------------------------- ### Install Kubernetes NuGet Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the necessary NuGet package for BSS Platform Kubernetes utilities. This package provides the foundation for integrating Kubernetes-specific features into your application. ```shell dotnet add package Luxoft.Bss.Platform.Kubernetes ``` -------------------------------- ### Register and Use Platform API Documentation Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the API documentation services and use the middleware in your application. This setup is environment-aware. ```csharp services .AddPlatformApiDocumentation(builder.Environment); app .UsePlatformApiDocumentation(builder.Environment); ``` -------------------------------- ### Add API Middlewares Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the platform API middlewares NuGet package using the dotnet CLI. ```shell dotnet add package Luxoft.Bss.Platform.Api.Middlewares ``` -------------------------------- ### Add BSS Platform Notifications NuGet Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the notifications NuGet package using the .NET CLI. ```shell dotnet add package Luxoft.Bss.Platform.Notifications ``` -------------------------------- ### Configure Serilog Sinks in appsettings.json Source: https://github.com/luxoft/bss-platform/blob/main/README.md Configure logging sinks and levels in the appsettings.json file using Serilog's configuration format. This example sets default information level and overrides for System and Microsoft namespaces. ```json { "Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "System": "Error", "Microsoft": "Error", "Microsoft.Hosting.Lifetime": "Information" } }, "WriteTo": [ { "Name": "Console", "Args": { "formatter": "Serilog.Formatting.Compact.RenderedCompactJsonFormatter, Serilog.Formatting.Compact" } } ] } } ``` -------------------------------- ### Add BSS Platform Notifications Audit NuGet Package Source: https://github.com/luxoft/bss-platform/blob/main/README.md Install the notifications audit NuGet package using the .NET CLI. ```shell dotnet add package Luxoft.Bss.Platform.Notifications.Audit ``` -------------------------------- ### Send Email Notification with Attachment Source: https://github.com/luxoft/bss-platform/blob/main/README.md Example of sending an email notification using IEmailSender. Supports attachments, including inlined attachments referenced by name. ```csharp public class YourNotificationRequestHandler(IEmailSender sender) : IRequestHandler { public async Task Handle(YourNotificationRequest request, CancellationToken cancellationToken) { var attachment = new Attachment(new MemoryStream(), request.AttachmentName); attachment.ContentDisposition!.Inline = true; var message = new EmailModel( request.Subject, request.Body, new MailAddress(request.From), new[] { new MailAddress(request.To) }, Attachments: new[] { attachment }); await sender.SendAsync(message, token); } } ``` -------------------------------- ### Configure Platform Logging with Serilog Source: https://context7.com/luxoft/bss-platform/llms.txt Sets up Serilog for logging, reading configurations from appsettings.json. Automatically forwards logs to Application Insights if TelemetryClient is registered. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Logging // Program.cs builder.Host.AddPlatformLogging(); // appsettings.json { "Serilog": { "MinimumLevel": { "Default": "Information", "Override": { "System": "Error", "Microsoft": "Error", "Microsoft.Hosting.Lifetime": "Information" } }, "WriteTo": [ { "Name": "Console", "Args": { "formatter": "Serilog.Formatting.Compact.RenderedCompactJsonFormatter, Serilog.Formatting.Compact" } } ] } } // Application Insights sink is added automatically if TelemetryClient is in DI. ``` -------------------------------- ### Add Platform Notifications via SMTP Source: https://context7.com/luxoft/bss-platform/llms.txt Configure and use the email sender service. In non-production environments, emails are redirected to a test list. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Notifications // appsettings.json { "NotificationSender": { "Server": "smtp.internal.com", "Port": 25, "DefaultRecipients": ["support@company.com"], "RedirectTo": ["dev-team@company.com"] // used in non-production environments } } // Program.cs builder.Services.AddPlatformNotifications(builder.Environment, builder.Configuration); // Usage public class WelcomeEmailHandler(IEmailSender sender) : IRequestHandler { public async Task Handle(SendWelcomeEmailCommand request, CancellationToken cancellationToken) { var attachment = new Attachment( new MemoryStream(request.PdfBytes), "welcome.pdf"); var message = new EmailModel( Subject: "Welcome aboard!", Body: $"

Hi {request.Name}

Welcome to the platform.

", From: new MailAddress("noreply@company.com"), To: [new MailAddress(request.RecipientEmail)], Attachments: [attachment]); await sender.SendAsync(message, cancellationToken); } } ``` -------------------------------- ### Register RabbitMQ Consumer with IRabbitMqMessageProcessor Source: https://github.com/luxoft/bss-platform/blob/main/README.md Implement the IRabbitMqMessageProcessor interface and use this method to register a consumer. The RoutingKeys section in RabbitMqConsumerSettings must contain all desired routing keys, or a '#' binding will be added if empty. ```csharp public class MessageProcessor : IRabbitMqMessageProcessor { public Task ProcessAsync(IBasicProperties properties, string routingKey, string message, CancellationToken token) { // write your consuming logic here } } ``` ```csharp services .AddPlatformRabbitMqClient(configuration) .AddPlatformRabbitMqConsumer(configuration); ``` -------------------------------- ### Register Platform Logging in DI Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the platform logger in the dependency injection container using the AddPlatformLogging host extension. ```csharp builder.Host.AddPlatformLogging(); ``` -------------------------------- ### Register RabbitMQ Consumer with Builder Source: https://github.com/luxoft/bss-platform/blob/main/README.md Implement IRabbitMqEventProcessor and use this method with a builder to explicitly register consumers for specific messages and routing keys. Ensure the RoutingKeys section in RabbitMqConsumerSettings is empty. ```csharp services .AddPlatformRabbitMqClient(configuration) .AddPlatformRabbitMqConsumerWithMessages( configuration, x => x .Add("RoutingKey1") .Add("RoutingKey2")); ``` ```csharp public interface IRabbitMqEventProcessor { Task ProcessAsync(TEvent @event, CancellationToken token); } ``` -------------------------------- ### Implement Integration Event Processor Source: https://github.com/luxoft/bss-platform/blob/main/README.md Implement the IIntegrationEventProcessor interface to define custom logic for processing incoming integration events. This is the first step in setting up the event handling mechanism. ```C# public class IntegrationEventProcessor : IIntegrationEventProcessor { public Task ProcessAsync(IIntegrationEvent @event, CancellationToken cancellationToken) { // write your consuming logic here } } ``` -------------------------------- ### Register RabbitMQ Client - AddPlatformRabbitMqClient Source: https://context7.com/luxoft/bss-platform/llms.txt Registers a resilient IRabbitMqClient singleton. Uses Polly for connection retries. Configure connection details in appsettings.json. The 'attempts' parameter controls retry count; null retries indefinitely. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.RabbitMq // appsettings.json { "RabbitMQ": { "Server": { "Host": "rabbitmq.internal", "Port": 5672, "UserName": "guest", "Secret": "guest", "VirtualHost": "/" } } } // Program.cs builder.Services.AddPlatformRabbitMqClient(builder.Configuration); // Direct usage (normally consumed internally by the Consumer package) public class MyStartup(IRabbitMqClient client) { public async Task ConnectAsync(CancellationToken ct) { // null = retry forever; pass an integer to limit attempts IConnection? connection = await client.TryConnectAsync(attempts: 5, ct); if (connection is null) Console.WriteLine("Could not connect after 5 attempts"); } } ``` -------------------------------- ### Register Integration Events in DI Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register integration events with the platform's dependency injection container. Configure connection details for SQL Server and RabbitMQ message queue. Ensure the correct assembly containing integration events is specified. ```C# services .AddPlatformIntegrationEvents( typeof(IntegrationEvents).Assembly, x => { x.SqlServer.ConnectionString = "ms sql connection string"; x.MessageQueue.ExchangeName = "integration.events"; x.MessageQueue.Host = "RabbitMQ host"; x.MessageQueue.Port = "RabbitMQ port"; x.MessageQueue.VirtualHost = "RabbitMQ virtual host"; x.MessageQueue.UserName = "RabbitMQ username"; x.MessageQueue.Secret = "RabbitMQ secret"; }); ``` -------------------------------- ### Configure Kubernetes Application Insights Source: https://context7.com/luxoft/bss-platform/llms.txt Configures Application Insights with Kubernetes pod enrichment. Options include capturing SQL command text, filtering health-check requests, and tagging authenticated users. Defaults are provided for all options. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Kubernetes builder.Services.AddPlatformKubernetesInsights( builder.Configuration, opt => { opt.RoleName = Environment.GetEnvironmentVariable("APP_NAME") ?? "my-service"; opt.SkipSuccessfulDependency = true; // don't record successful SQL/HTTP calls opt.SkipDefaultHealthChecks = true; // suppress /health/live and /health/ready opt.AdditionalHealthCheckPathToSkip = ["/DoHealthCheck", "/ping"]; opt.SetAuthenticatedUserFromHttpContext = true; }); // Kubernetes pod metadata (namespace, node, etc.) is automatically enriched via // Microsoft.ApplicationInsights.Kubernetes. ``` -------------------------------- ### Implement Domain Events with In-Process Dispatching Source: https://context7.com/luxoft/bss-platform/llms.txt Provides in-process domain event dispatching using IMediator. Events are published synchronously and handled by registered INotificationHandler implementations. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Events // Event definition public record OrderShippedEvent(Guid OrderId, DateTimeOffset ShippedAt) : IDomainEvent, INotification; // Handler public class SendShippingEmailHandler : INotificationHandler { public Task Handle(OrderShippedEvent notification, CancellationToken cancellationToken) => Console.Out.WriteLineAsync($"Sending shipping email for order {notification.OrderId}"); } // Registration builder.Services .AddPlatformDomainEvents() .AddMediation(typeof(SendShippingEmailHandler).Assembly); // Usage inside a command handler public class ShipOrderHandler(IDomainEventPublisher publisher) : IRequestHandler { public async Task Handle(ShipOrderCommand request, CancellationToken cancellationToken) { // ... perform shipping logic ... await publisher.PublishAsync( new OrderShippedEvent(request.OrderId, DateTimeOffset.UtcNow), cancellationToken); } } ``` -------------------------------- ### Mock IQueryable Repository Source: https://github.com/luxoft/bss-platform/blob/main/README.md Mock an IQueryable repository for unit testing purposes using the TestQueryable class. This allows you to control the data returned by the repository during tests. ```C# var entity = new Entity(); repository.GetQueryable().Returns(new TestQueryable(entity)); ``` -------------------------------- ### Register Low-Level RabbitMQ Consumer Source: https://context7.com/luxoft/bss-platform/llms.txt Use `AddPlatformRabbitMqConsumer` for the low-level `IRabbitMqMessageProcessor` interface, which provides raw AMQP properties, routing key, and JSON string. Routing keys must be explicitly listed in `appsettings.json`. This is suitable for custom deserialization or fine-grained AMQP control. ```csharp public class LegacyProcessor : IRabbitMqMessageProcessor { public Task ProcessAsync( IBasicProperties properties, string routingKey, string message, CancellationToken token) { Console.WriteLine($"[{routingKey}] Headers: {properties.Headers?.Count ?? 0}, Body: {message}"); return Task.CompletedTask; } } // Program.cs builder.Services .AddPlatformRabbitMqClient(builder.Configuration) .AddPlatformRabbitMqConsumer(builder.Configuration); // appsettings.json – RoutingKeys must be populated manually here { "RabbitMQ": { "Consumer": { "Exchange": "legacy", "Queue": "legacy-queue", "RoutingKeys": ["legacy.event.one", "legacy.event.two"] } } } ``` -------------------------------- ### Add Platform API Documentation with Swagger Source: https://context7.com/luxoft/bss-platform/llms.txt Registers and exposes Swagger/OpenAPI documentation with Bearer token security. Disabled in Production environments. Configures Swagger UI and JSON spec endpoints. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Api.Documentation // Program.cs builder.Services.AddPlatformApiDocumentation( builder.Environment, title: "Orders API", setupAction: x => { x.SwaggerDoc("v2", new OpenApiInfo { Title = "Orders API v2", Version = "v2" }); }); app.UsePlatformApiDocumentation(builder.Environment, path: "swagger"); // Swagger UI available at: /swagger (non-production only) // JSON spec at: /swagger/api/swagger.json ``` -------------------------------- ### Configure RabbitMQ JSON Schema Generator Middleware Source: https://github.com/luxoft/bss-platform/blob/main/README.md Use this extension to add the RabbitMQ JSON Schema Generator middleware. Configure the path, system prefix for produced types, and the collection of produced event types. ```csharp if (app.Environment.IsDevelopment()) { app.UseRabbitJsonSchemaGenerator(opt => { opt.Path = "/api/rabbit-json-schema"; opt.SystemPrefix = "TSS."; opt.ProducedEventTypes = typeof(IEvent).Assembly.GetTypes() .Where(x => x.IsPublic && !x.IsAbstract && !x.IsInterface) .Where(x => x.GetInterfaces().Contains(typeof(IEvent))); }); } ``` -------------------------------- ### Register RabbitMQ Consumer with Attribute Routing Keys Source: https://context7.com/luxoft/bss-platform/llms.txt Use `AddPlatformRabbitMqConsumerWithMessages` when message types have custom attributes defining their routing keys. The package automatically builds the routing-key map by scanning the attribute's assembly at startup. ```csharp public class RabbitEventAttribute(string routingKey) : Attribute { public string RoutingKey { get; } = routingKey; } [RabbitEvent("inventory.updated")] public record InventoryUpdated(Guid ProductId, int NewStock) : IInventoryEvent; [RabbitEvent("inventory.reserved")] public record InventoryReserved(Guid ProductId, int Quantity) : IInventoryEvent; public class InventoryProcessor : IRabbitMqEventProcessor { public Task ProcessAsync(IInventoryEvent @event, CancellationToken token) => Console.Out.WriteLineAsync(@event.ToString()); } // Program.cs builder.Services .AddPlatformRabbitMqClient(builder.Configuration) .AddPlatformRabbitMqConsumerWithMessages( builder.Configuration, attr => attr.RoutingKey); ``` -------------------------------- ### Register Domain Events in DI Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the domain events services in the dependency injection container. ```csharp services .AddPlatformDomainEvents(); ``` -------------------------------- ### Register RabbitMQ Consumer with Attribute Source: https://github.com/luxoft/bss-platform/blob/main/README.md Implement IRabbitMqEventProcessor and use this method to register consumers that handle events marked with a RabbitEvent attribute. Ensure the RoutingKeys section in RabbitMqConsumerSettings is empty. ```csharp services .AddPlatformRabbitMqClient(configuration) .AddPlatformRabbitMqConsumerWithMessages( configuration, x => x.RoutingKey); ``` ```csharp public interface IRabbitMqEventProcessor { Task ProcessAsync(TEvent @event, CancellationToken token); } ``` ```csharp public class RabbitEventAttribute(string routingKey) : Attribute { public string RoutingKey { get; } = routingKey; } [RabbitEvent("RoutingKey1")] public record MessageOne(string Name, Guid Id): IRequest; ``` -------------------------------- ### Register Kubernetes Health Checks Source: https://context7.com/luxoft/bss-platform/llms.txt Registers SQL Server liveness and readiness probes for Kubernetes. The simple form uses default check names, while the extended form allows custom check names and integration with external health checks. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Kubernetes // Registration (simple form) builder.Services.AddPlatformKubernetesHealthChecks( builder.Configuration.GetConnectionString("Default")!); app.UsePlatformKubernetesHealthChecks(); // GET /health/live → 200 OK (no checks, just alive) // GET /health/ready → 200 OK (SQL Server connectivity check passes) // Extended form – custom check names builder.Services .AddPlatformKubernetesHealthChecks( builder.Configuration.GetConnectionString("Default")!, sqlCheckName: "sql-main") .AddUrlGroup(new Uri("https://ext-api/health"), name: "ext-api"); app.UsePlatformKubernetesHealthChecks("sql-main", "ext-api"); ``` -------------------------------- ### Register BSS Platform Notifications Service Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the notifications service in the Dependency Injection container. ```csharp services .AddPlatformNotifications(builder.Environment, builder.Configuration) ``` -------------------------------- ### Configure Notification Sender Settings Source: https://github.com/luxoft/bss-platform/blob/main/README.md Configure the NotificationSender settings in the application's configuration file. This includes server details, redirect addresses for non-production environments, and default recipients. ```json { "NotificationSender": { "Server": "smtp.server.com", // smtp server host "RedirectTo": ["test@email.com"], // all messages on non-prod environments will be sent to these addresses, recipients will be listed in message body "DefaultRecipients": ["your_support@email.com"] // if no recipients are provided for a message then these emails will become recipients } } ``` -------------------------------- ### Register RabbitMQ Consumer - AddPlatformRabbitMqConsumerWithMessages Source: https://context7.com/luxoft/bss-platform/llms.txt Registers a typed RabbitMQ consumer with fluent routing-key-to-message-type mappings. Deserializes JSON payloads and dispatches to an IRabbitMqEventProcessor. The RoutingKeys config section must be absent or empty. Configure exchange, queue, and consumer mode in appsettings.json. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.RabbitMq.Consumer // Message contracts public interface IOrderEvent { } public record OrderCreated(Guid OrderId, string Customer) : IOrderEvent; public record OrderCancelled(Guid OrderId, string Reason) : IOrderEvent; // Processor public class OrderEventProcessor : IRabbitMqEventProcessor { public Task ProcessAsync(IOrderEvent @event, CancellationToken token) { return @event switch { OrderCreated e => Console.Out.WriteLineAsync($"Created: {e.OrderId}"), OrderCancelled e => Console.Out.WriteLineAsync($"Cancelled: {e.OrderId}"), _ => Task.CompletedTask }; } } // Program.cs builder.Services .AddPlatformRabbitMqClient(builder.Configuration) .AddPlatformRabbitMqConsumerWithMessages( builder.Configuration, x => x .Add("orders.created") .Add("orders.cancelled")); // appsettings.json – RoutingKeys MUST be absent / empty { "RabbitMQ": { "Consumer": { "Exchange": "orders", "Queue": "orders-service", "Mode": "MultipleActiveConsumers", // or "SingleActiveConsumer" "FailedMessageRetryCount": 3 } } } ``` -------------------------------- ### Process Integration Event Source: https://github.com/luxoft/bss-platform/blob/main/README.md Handle incoming integration events by implementing the INotificationHandler interface. This is where the consuming logic for specific integration events resides. ```C# public class EventHandler : INotificationHandler { public async Task Handle(IntegrationEvent notification, CancellationToken cancellationToken) { // your logic } } ``` -------------------------------- ### Add Custom Mediation to DI Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the custom mediation system by calling AddMediation and passing the assembly containing handlers and pipeline behaviors. ```csharp builder.Services.AddMediation(typeof(DependencyInjection).Assembly); ``` -------------------------------- ### Manually Register RabbitMQ Schema Generator Middleware Source: https://github.com/luxoft/bss-platform/blob/main/README.md For more complex scenarios, manually register the GenerateSchemaMiddleware. This requires providing a dictionary mapping routing keys to event types for both consumed and produced events. ```csharp app.UseMiddleware("/api/rabbit-json-schema", allEventsDict); ``` -------------------------------- ### Add Health Checks Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register health check services with a database connection string and enable the health check middleware. This makes health status available at /health/live and /health/ready endpoints. ```C# services .AddPlatformKubernetesHealthChecks("your db connection string"); app .UsePlatformKubernetesHealthChecks(); ``` -------------------------------- ### Expose RabbitMQ JSON Schema Generator Source: https://context7.com/luxoft/bss-platform/llms.txt Use `UseRabbitJsonSchemaGenerator` to expose an HTTP endpoint that generates a JSON Schema document for RabbitMQ event types. This is typically used in development environments. Consumed types are discovered automatically, while produced types must be passed explicitly. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.RabbitMq.JsonSchemaGenerator // Program.cs – after consumer registration if (app.Environment.IsDevelopment()) { app.UseRabbitJsonSchemaGenerator(opt => { opt.Path = "/api/rabbit-json-schema"; opt.SystemPrefix = "Orders."; // produced types get this prefix in the schema opt.ProducedEventTypes = typeof(IOrderEvent).Assembly .GetTypes() .Where(t => t.IsPublic && !t.IsAbstract && !t.IsInterface) .Where(t => t.GetInterfaces().Contains(typeof(IOrderEvent))); }); } // GET /api/rabbit-json-schema // Returns a JSON Schema object with keys like "Orders.OrderShipped", "orders.created", etc. ``` -------------------------------- ### Unit Test NHibernate Queries with TestQueryable Source: https://context7.com/luxoft/bss-platform/llms.txt Use TestQueryable to mock IOrderedQueryable for unit tests. This allows NHibernate-specific extension methods like Fetch and ToListAsync to be tested without a database. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.NHibernate.UnitTesting public class OrderRepositoryTests { [Fact] public async Task GetPendingOrders_ReturnsMappedDtos() { // Arrange – seed in-memory data var orders = new[] { new Order { Id = Guid.NewGuid(), Status = "Pending", Customer = "Alice" }, new Order { Id = Guid.NewGuid(), Status = "Shipped", Customer = "Bob" }, new Order { Id = Guid.NewGuid(), Status = "Pending", Customer = "Carol" } }; var repository = Substitute.For(); repository.GetQueryable() .Returns(new TestQueryable(orders)); var sut = new OrderService(repository); // Act var result = await sut.GetPendingOrdersAsync(CancellationToken.None); // Assert – NHibernate Fetch / ToListAsync work transparently result.Should().HaveCount(2); result.Should().AllSatisfy(o => o.Status.Should().Be("Pending")); } } ``` -------------------------------- ### Register Pipeline Behaviors for Custom Mediation Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register pipeline behaviors as open generics for the custom mediation system. The order of registration determines the execution order (outer to inner). ```csharp // Outer → inner builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ExceptionMappingBehavior<,>)); builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(TransactionBehavior<,>)); ``` -------------------------------- ### Register Integration Events with Custom Processor Source: https://context7.com/luxoft/bss-platform/llms.txt Registers integration event publishing and consumption. Configure SQL Server, RabbitMQ transport, retry counts, and message retention. Set `MessageQueue.Enable = false` for in-memory queues during local development. An authorization predicate can be provided to control access to the monitoring dashboard. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Events // Event contract public record PaymentProcessed(Guid PaymentId, decimal Amount) : IIntegrationEvent, INotification; // Consumer processor public class PaymentEventProcessor : IIntegrationEventProcessor { public Task ProcessAsync(IIntegrationEvent @event, CancellationToken cancellationToken) { if (@event is PaymentProcessed p) Console.WriteLine($"Payment {p.PaymentId}: {p.Amount:C}"); return Task.CompletedTask; } } // Registration builder.Services.AddPlatformIntegrationEvents( typeof(PaymentProcessed).Assembly, x => { x.SqlServer.ConnectionString = builder.Configuration.GetConnectionString("Default")!; x.MessageQueue.ExchangeName = "payments"; x.MessageQueue.Host = "rabbitmq.internal"; x.MessageQueue.Port = 5672; x.MessageQueue.VirtualHost = "/"; x.MessageQueue.UserName = "guest"; x.MessageQueue.Secret = "guest"; x.FailedRetryCount = 5; x.RetentionDays = 15; x.DashboardPath = "/admin/events"; x.AuthorizationPredicate = ctx => Task.FromResult(ctx.User.IsInRole("Admin")); }); // Publishing public class ProcessPaymentHandler(IIntegrationEventPublisher publisher) : IRequestHandler { public async Task Handle(ProcessPaymentCommand request, CancellationToken cancellationToken) { // ... process payment ... await publisher.PublishAsync( new PaymentProcessed(request.PaymentId, request.Amount), cancellationToken); } } ``` -------------------------------- ### Add Custom Mediation Source: https://context7.com/luxoft/bss-platform/llms.txt Register and configure the in-process mediator. Handlers and behaviors are discovered by assembly scanning. ```csharp // Install: dotnet package Luxoft.Bss.Platform.Mediation // --- Contracts --- public record GetUserQuery(Guid UserId) : IRequest; public record DeleteUserCommand(Guid UserId) : IRequest; // void public record UserDeletedNotification(Guid UserId) : INotification; // --- Handlers --- public class GetUserHandler : IRequestHandler { public Task Handle(GetUserQuery request, CancellationToken cancellationToken) => Task.FromResult(new UserDto(request.UserId, "Alice")); } public class DeleteUserHandler(IDomainEventPublisher events) : IRequestHandler { public async Task Handle(DeleteUserCommand request, CancellationToken cancellationToken) { // delete from DB... await events.PublishAsync(new UserDeletedNotification(request.UserId), cancellationToken); } } // --- Pipeline behaviour --- public class ValidationBehavior(IValidator validator) : IPipelineBehavior { public async Task Handle( TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { await validator.ValidateAndThrowAsync(request, cancellationToken); return await next(); } } // --- Registration --- builder.Services.AddMediation(typeof(GetUserHandler).Assembly); // Pipeline behaviours are registered separately; order = outer → inner builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); // --- Usage in a controller --- public class UsersController(IMediator mediator) : ControllerBase { [HttpGet("{id}")] public Task Get(Guid id, CancellationToken ct) => mediator.Send(new GetUserQuery(id), ct); [HttpDelete("{id}")] public Task Delete(Guid id, CancellationToken ct) => mediator.Send(new DeleteUserCommand(id), ct); } ``` -------------------------------- ### Publish Integration Event Source: https://github.com/luxoft/bss-platform/blob/main/README.md Publish an integration event using the injected IIntegrationEventPublisher. This is typically done within a command handler after a command has been successfully processed. ```C# public class CommandHandler(IIntegrationEventPublisher eventPublisher) : IRequestHandler { public async Task Handle(Command request, CancellationToken cancellationToken) { await eventPublisher.PublishAsync(new IntegrationEvent(), cancellationToken); } } ``` -------------------------------- ### Register Platform Errors Middleware Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the platform errors middleware. This middleware should be the first one in the pipeline to handle exceptions. ```csharp app.UsePlatformErrorsMiddleware(); // This middleware should be the first ``` -------------------------------- ### Handle Domain Event Source: https://github.com/luxoft/bss-platform/blob/main/README.md Process incoming domain events by implementing the INotificationHandler interface. The notification parameter will be the domain event type. ```csharp public class EventHandler : INotificationHandler { public async Task Handle(DomainEvent notification, CancellationToken cancellationToken) { // your logic } } ``` -------------------------------- ### Configure Single Active Consumer Mode Source: https://github.com/luxoft/bss-platform/blob/main/README.md To enable the Single Active Consumer mode for RabbitMQ consumers, set the 'Mode' property in the RabbitMQ Consumer configuration in appsettings.json. ```json { "RabbitMQ": { "Consumer": { "Mode": "SingleActiveConsumer" } } } ``` -------------------------------- ### Implement API Error Handling Middleware Source: https://context7.com/luxoft/bss-platform/llms.txt Catches unhandled exceptions in the ASP.NET Core pipeline, logs them, and returns a plain-text response. Optionally maps exceptions to custom HTTP status codes using IStatusCodeResolver. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Api.Middlewares // Custom HTTP status mapping public class AppStatusCodeResolver : IStatusCodeResolver { public HttpStatusCode Resolve(Exception exception) => exception switch { KeyNotFoundException => HttpStatusCode.NotFound, UnauthorizedAccessException => HttpStatusCode.Forbidden, ArgumentException => HttpStatusCode.BadRequest, _ => HttpStatusCode.InternalServerError }; } // Program.cs – must be registered FIRST in the pipeline app.UsePlatformErrorsMiddleware(); app.UseRouting(); app.MapControllers(); // DI registration (optional) builder.Services.AddSingleton(); // Result for an unhandled KeyNotFoundException: // HTTP 404 – "The given key was not present in the dictionary." ``` -------------------------------- ### Register Custom Status Code Resolver Source: https://github.com/luxoft/bss-platform/blob/main/README.md If you need to change the response status code, register a custom implementation of IStatusCodeResolver as a singleton service. ```csharp services.AddSingleton(); ``` -------------------------------- ### Publish Domain Event Source: https://github.com/luxoft/bss-platform/blob/main/README.md Publish a domain event using the IDomainEventPublisher. This is typically done within a command handler. ```csharp public class CommandHandler(IDomainEventPublisher eventPublisher) : IRequestHandler { public async Task Handle(Command request, CancellationToken cancellationToken) { await eventPublisher.PublishAsync(new DomainEvent(), cancellationToken); } } ``` -------------------------------- ### Enable Single Active Consumer Lock with SQL Server Source: https://context7.com/luxoft/bss-platform/llms.txt Use `AddPlatformRabbitMqSqlServerConsumerLock` to enable `SingleActiveConsumer` mode by storing a distributed lock in SQL Server. This ensures only one service replica actively consumes messages when multiple replicas run simultaneously. ```csharp builder.Services .AddPlatformRabbitMqClient(builder.Configuration) .AddPlatformRabbitMqConsumerWithMessages( builder.Configuration, x => x.Add("orders.created")) .AddPlatformRabbitMqSqlServerConsumerLock( builder.Configuration.GetConnectionString("DefaultConnection")!); // appsettings.json { "RabbitMQ": { "Consumer": { "Mode": "SingleActiveConsumer", "InactiveConsumerSleepMilliseconds": 60000, // how often inactive replicas retry "ActiveConsumerRefreshMilliseconds": 180000 // how often the active replica refreshes } } } ``` -------------------------------- ### Add Platform Notifications Audit Source: https://context7.com/luxoft/bss-platform/llms.txt Enable persistence of sent emails to a SQL Server table. The schema and table are created automatically on application startup. ```csharp // Install: dotnet add package Luxoft.Bss.Platform.Notifications.Audit builder.Services.AddPlatformNotificationsAudit(o => { o.ConnectionString = builder.Configuration.GetConnectionString("Default")!; o.Schema = "notifications"; // default o.Table = "SentMessages"; // default }); // On startup the hosted service runs DDL to create [notifications].[SentMessages] // if it does not exist. Every IEmailSender.SendAsync call writes an audit row. ``` -------------------------------- ### Register BSS Platform Notifications Audit Service Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the notifications audit service in the Dependency Injection container, providing the SQL connection string. ```csharp services .AddPlatformNotificationsAudit(o => o.ConnectionString = builder.Configuration.GetConnectionString("DefaultConnection")!); ``` -------------------------------- ### AddMediation - IMediator Source: https://context7.com/luxoft/bss-platform/llms.txt A lightweight in-process mediator that supports request/response, fire-and-forget requests, fan-out notifications, and ordered pipeline behaviours. Handlers and behaviours are discovered by assembly scanning. ```APIDOC ## Custom Mediation — `AddMediation` / `IMediator` ### Description A lightweight in-process mediator that replaces MediatR-style usage. Supports request/response, fire-and-forget (void) requests, fan-out notifications, and ordered pipeline behaviours. Handlers and behaviours are discovered by assembly scanning. ### Registration ```csharp builder.Services.AddMediation(typeof(GetUserHandler).Assembly); // Pipeline behaviours are registered separately; order = outer → inner builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); ``` ### Usage Example ```csharp public class UsersController(IMediator mediator) : ControllerBase { [HttpGet("{id}")] public Task Get(Guid id, CancellationToken ct) => mediator.Send(new GetUserQuery(id), ct); [HttpDelete("{id}")] public Task Delete(Guid id, CancellationToken ct) => mediator.Send(new DeleteUserCommand(id), ct); } ``` ``` -------------------------------- ### Register Application Insights Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register application insights services in the dependency injection container. Configure options such as skipping successful dependencies, setting the role name, and specifying additional health check paths to skip. ```C# services .AddPlatformKubernetesInsights( builder.Configuration, opt => { opt.SkipSuccessfulDependency = true; opt.RoleName = Environment.GetEnvironmentVariable("APP_NAME"); opt.AdditionalHealthCheckPathToSkip = ["/DoHealthCheck"]; }); ``` -------------------------------- ### AddPlatformNotificationsAudit Source: https://context7.com/luxoft/bss-platform/llms.txt Persists a record of every sent email to a SQL Server table. The schema and table are created automatically on application startup via a hosted migration service. ```APIDOC ## Notifications Audit — `AddPlatformNotificationsAudit` ### Description Persists a record of every sent email to a SQL Server table. The schema and table are created automatically on application startup via a hosted migration service. ### Registration ```csharp builder.Services.AddPlatformNotificationsAudit(o => { o.ConnectionString = builder.Configuration.GetConnectionString("Default")!; o.Schema = "notifications"; // default o.Table = "SentMessages"; // default }); // On startup the hosted service runs DDL to create [notifications].[SentMessages] // if it does not exist. Every IEmailSender.SendAsync call writes an audit row. ``` ``` -------------------------------- ### Register RabbitMQ SQL Server Consumer Lock Source: https://github.com/luxoft/bss-platform/blob/main/README.md Register the SQL Server consumer lock service in DI to manage consumer locking, typically used with the Single Active Consumer mode. ```csharp services .AddPlatformRabbitMqSqlServerConsumerLock(configuration.GetConnectionString("ms sql connection string")); ``` -------------------------------- ### AddPlatformNotifications - IEmailSender Source: https://context7.com/luxoft/bss-platform/llms.txt Provides email delivery via SMTP. In non-production environments, outgoing messages are redirected to a configured test address list while preserving original recipients in the message body. ```APIDOC ## AddPlatformNotifications - IEmailSender ### Description Provides email delivery via SMTP (or file-based output). In non-production environments all outgoing messages are transparently redirected to a configured test address list while preserving the original recipients in the message body. ### Registration ```csharp builder.Services.AddPlatformNotifications(builder.Environment, builder.Configuration); ``` ### Usage Example ```csharp public class WelcomeEmailHandler(IEmailSender sender) : IRequestHandler { public async Task Handle(SendWelcomeEmailCommand request, CancellationToken cancellationToken) { var attachment = new Attachment( new MemoryStream(request.PdfBytes), "welcome.pdf"); var message = new EmailModel( Subject: "Welcome aboard!", Body: $"

Hi {request.Name}

Welcome to the platform.

", From: new MailAddress("noreply@company.com"), To: [new MailAddress(request.RecipientEmail)], Attachments: [attachment]); await sender.SendAsync(message, cancellationToken); } } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.