Skip to content

Configuration Pipelines

quyvu edited this page Oct 13, 2026 · 2 revisions

Pipeline Configuration

Configure send and receive pipelines to add cross-cutting concerns like logging, validation, and transformation to your FxMap requests and responses.

What Are Pipelines?

Pipelines are middleware-like components that intercept and process requests and responses in the FxMap data flow. They enable you to add cross-cutting concerns without modifying your core business logic.

Send Pipelines

Process outgoing requests before they are sent to handlers or remote services. Run on the client side.

Receive Pipelines

Process incoming requests before they reach handlers. Run on the server side where data is fetched.

Pipeline Flow

Client

Send Pipeline

Transport

Transport

Receive Pipeline

Server Handler

Server Handler

Response

Client

Configuring Send Pipelines

Send pipelines are configured on the client side:

builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
 
    // Add send pipelines
    cfg.AddSendPipelines(c =>
    {
        // Add a generic pipeline
        c.OfType(typeof(GenericSendPipeline<>))
         .OfType(typeof(LoggingSendPipeline<>));
    });
});

Creating a Send Pipeline

Send pipelines implement request preprocessing logic before data is sent to the server:

using FxMap.Abstractions;
using FxMap.Delegates;
using FxMap.Responses;
 
public sealed class LoggingSendPipeline<TKey>(ILogger logger) :
    ISendPipelineBehavior<TKey> where TKey : IDistributedKey
{
    public async Task<ItemsResponse<DataResponse>> HandleAsync(
        RequestContext<TKey> requestContext,
        SendHandlerDelegate next)
    {
        logger.Information("Sending request for key {Key}", typeof(TKey).Name);
        var result = await next.Invoke();
        return result;
    }
}

Configuring Receive Pipelines

Receive pipelines are configured on the server side where you handle incoming requests:

builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
 
    // Add receive pipelines
    cfg.AddReceivedPipelines(c =>
    {
        // Add a generic pipeline
        c.OfType(typeof(GenericReceivedPipeline<>))
         .OfType(typeof(LoggingReceivedPipeline<>));
    });
});

Creating a Receive Pipeline

Receive pipelines process incoming requests before they reach your handlers:

using FxMap.Abstractions;
using FxMap.Delegates;
using FxMap.Responses;
 
public sealed class LoggingReceivedPipeline<TKey>(ILogger logger) :
    IReceivedPipelineBehavior<TKey> where TKey : IDistributedKey
{
    public async Task<ItemsResponse<DataResponse>> HandleAsync(
        RequestContext<TKey> requestContext,
        ReceivedHandlerDelegate next)
    {
        logger.Information("Received request for key {Key}", typeof(TKey).Name);
        var result = await next.Invoke();
        return result;
    }
}

Common Pipeline Use Cases

Logging & Monitoring

Track request/response flows, measure performance, and identify bottlenecks.

Authentication & Authorization

Validate user permissions before allowing data access.

Caching

Cache responses to reduce database load and improve performance.

Validation

Validate request parameters and data integrity.

Data Transformation

Transform or enrich data before it's processed or returned.

Complete Pipeline Example

// Program.cs - Client Side
builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
 
    // Configure send pipelines (client side)
    cfg.AddSendPipelines(c =>
    {
        c.OfType(typeof(LoggingSendPipeline<>));
        c.OfType<PerformanceMonitoringSendPipeline>();
    });
})
.AddRabbitMq(config => { ... });
 
// Program.cs - Server Side
builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
 
    // Configure receive pipelines (server side)
    cfg.AddReceivedPipelines(c =>
    {
        c.OfType<AuthorizationReceivedPipeline>();
        c.OfType<CachingReceivedPipeline>();
        c.OfType<ValidationReceivedPipeline>();
    });
})
.AddEntityFrameworkCore(options => options.AddDbContexts(typeof(AppDbContext)))
.AddRabbitMq(config => { ... });

Best Practices

  • Keep pipelines focused on a single responsibility
  • Order matters - pipelines execute in the order they are registered
  • Always call next() to continue the pipeline chain
  • Use dependency injection for pipeline dependencies
  • Handle exceptions appropriately to avoid breaking the pipeline

Important Notes

  • Send pipelines run on the client, receive pipelines run on the server
  • Pipelines are optional - FxMap works without them
  • Not calling next() will short-circuit the pipeline
  • Generic pipelines (TKey) allow key-specific processing

Source: https://fxmapper.net/docs/configuration/pipelines/ — the website is always the most up to date version.

Clone this wiki locally