Migrating from MediatR to LiteBus

This guide provides a step-by-step technical walkthrough for migrating a .NET application from MediatR to LiteBus. It maps MediatR’s concepts directly to their LiteBus equivalents, focusing on code and configuration changes.

Since MediatR is shifting …


This content originally appeared on DEV Community and was authored by A. Shafie

This guide provides a step-by-step technical walkthrough for migrating a .NET application from MediatR to LiteBus. It maps MediatR's concepts directly to their LiteBus equivalents, focusing on code and configuration changes.

Since MediatR is shifting to a commercial model, LiteBus offers a powerful, free, and open-source alternative with a more ambitious feature set.

Core Philosophy: From Generic to Semantic

The primary difference between the two libraries is their approach to abstractions:

  • MediatR uses a generic IRequest<TResponse> for both commands and queries.
  • LiteBus provides distinct ICommand<TResult>, IQuery<TResult>, and IEvent interfaces.

This semantic distinction in LiteBus enforces Command Query Separation (CQS) at the compiler level, making your application's intent clearer.

Step 1: Update Project Dependencies

First, replace the MediatR packages with the LiteBus equivalents.

Remove MediatR:

dotnet remove MediatR

Add LiteBus:

# Core DI extension (pulls in Command, Query, Event modules)
dotnet add package LiteBus.Extensions.Microsoft.DependencyInjection

# Optional: For referencing only abstractions in domain/app layers
dotnet add package LiteBus.Commands.Abstractions
dotnet add package LiteBus.Queries.Abstractions
dotnet add package LiteBus.Events.Abstractions

Step 2: Update Dependency Injection (Program.cs)

The registration process is similar. LiteBus scans assemblies to discover handlers automatically.

Before (MediatR):

builder.Services.AddMediatR(cfg => 
{
    cfg.LicenseKey = "<License Key here>";
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
});

After (LiteBus):

builder.Services.AddLiteBus(liteBus =>
{
    var appAssembly = typeof(Program).Assembly;

    // Each module scans for its specific constructs (handlers, validators, etc.)
    liteBus.AddCommandModule(module => module.RegisterFromAssembly(appAssembly));
    liteBus.AddQueryModule(module => module.RegisterFromAssembly(appAssembly));
    liteBus.AddEventModule(module => module.RegisterFromAssembly(appAssembly));
});

Step 3: Convert Message Contracts

This is a direct mapping of interfaces.

Requests (Commands and Queries)

  • IRequest -> ICommand
  • IRequest<TResponse> -> ICommand<TResponse> (for state changes) or IQuery<TResponse> (for data retrieval).

Before (MediatR):

// Command
public class ShipOrderCommand : IRequest { ... }

// Query
public class GetProductQuery : IRequest<ProductDto> { ... }

After (LiteBus):

// Command
public class ShipOrderCommand : ICommand { ... }

// Query
public class GetProductQuery : IQuery<ProductDto> { ... }

Notifications (Events)

  • INotification -> IEvent or a Plain Old C# Object (POCO).

Before (MediatR):

public class OrderShippedEvent : INotification { ... }

After (LiteBus):

// Option 1: Using the interface
public class OrderShippedEvent : IEvent { ... }

// Option 2: Using a POCO (recommended for domain events)
public class OrderShippedEvent { ... }

Step 4: Convert Handlers

Handler interfaces also map directly.

Before (MediatR):

public class ShipOrderCommandHandler : IRequestHandler<ShipOrderCommand> { ... }
public class GetProductQueryHandler : IRequestHandler<GetProductQuery, ProductDto> { ... }
public class OrderShippedEventHandler : INotificationHandler<OrderShippedEvent> { ... }

After (LiteBus):

public class ShipOrderCommandHandler : ICommandHandler<ShipOrderCommand> { ... }
public class GetProductQueryHandler : IQueryHandler<GetProductQuery, ProductDto> { ... }
public class OrderShippedEventHandler : IEventHandler<OrderShippedEvent> { ... }

Step 5: Convert Pipeline Behaviors and Processors

MediatR uses IPipelineBehavior for cross-cutting concerns and has separate pre/post-processors. LiteBus unifies this into a structured pipeline of Pre-Handler, Post-Handler, and Error-Handler.

  • IRequestPreProcessor<TRequest> -> ICommandPreHandler<TCommand>
  • IRequestPostProcessor<TRequest, TResponse> -> ICommandPostHandler<TCommand, TResponse>
  • IPipelineBehavior logic can be split into pre and post handlers.

Let's convert a MediatR LoggingBehavior.

Before (MediatR):

public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : notnull
{
    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken ct)
    {
        // Pre-logic
        _logger.LogInformation("Handling {RequestName}", typeof(TRequest).Name);
        var response = await next();
        // Post-logic
        _logger.LogInformation("Handled {RequestName}", typeof(TRequest).Name);
        return response;
    }
}

After (LiteBus):

The logic is split into two distinct, globally-scoped handlers.

// This runs BEFORE every command.
public class GlobalLoggingPreHandler : ICommandPreHandler
{
    public Task PreHandleAsync(ICommand command, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Handling {CommandName}", command.GetType().Name);
        return Task.CompletedTask;
    }
}

// This runs AFTER every command.
public class GlobalLoggingPostHandler : ICommandPostHandler
{
    public Task PostHandleAsync(ICommand command, object? result, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Handled {CommandName}", command.GetType().Name);
        return Task.CompletedTask;
    }
}

Step 6: Convert Exception Handling

MediatR uses IRequestExceptionHandler and IRequestExceptionAction. LiteBus uses a single, powerful IErrorHandler concept that can be scoped globally or to a specific message.

Before (MediatR):

public class MyExceptionHandler : IRequestExceptionHandler<MyRequest, MyResponse, MyException>
{
    public Task Handle(MyRequest request, MyException exception, RequestExceptionHandlerState<MyResponse> state, CancellationToken cancellationToken)
    {
        // Handle the exception, potentially setting a response
        state.SetHandled(new MyResponse());
        return Task.CompletedTask;
    }
}

After (LiteBus):

public class MyErrorHandler : ICommandErrorHandler<MyCommand>
{
    public Task HandleErrorAsync(MyCommand command, object? messageResult, Exception exception, CancellationToken cancellationToken)
    {
        if (exception is MyException myException)
        {
            // Access the execution context to set a result and stop the exception
            AmbientExecutionContext.Current.Abort(new MyCommandResult());
        }
        // If Abort() is not called, the original exception will be re-thrown
        return Task.CompletedTask;
    }
}

Step 7: Update Dispatching Code

Instead of a single IMediator, LiteBus provides specific interfaces.

Before (MediatR):

public class MyController
{
    private readonly IMediator _mediator;
    public async Task MyAction()
    {
        await _mediator.Send(new MyCommand());
        await _mediator.Publish(new MyEvent());
    }
}

After (LiteBus):

public class MyController
{
    private readonly ICommandMediator _commandMediator;
    private readonly IEventPublisher _eventPublisher;
    public async Task MyAction()
    {
        await _commandMediator.SendAsync(new MyCommand());
        await _eventPublisher.PublishAsync(new MyEvent());
    }
}

More Features of LiteBus

MediatR is, by its own definition, a "low-ambition" library. LiteBus is more ambitious and provides built-in solutions for complex, enterprise-level problems. Once migrated, you have access to:

  • Durable Command Inbox: Guarantee at-least-once execution of critical commands with the [StoreInInbox] attribute. This provides message-queue-like resilience for in-process operations without adding heavy infrastructure.
  • Advanced Event Concurrency: Configure event handlers to run sequentially or in parallel, both within priority groups and across them. This is essential for performance tuning complex event-driven workflows.
  • First-Class Streaming: Use IStreamQuery<T> and IAsyncEnumerable<T> to efficiently handle large datasets without high memory usage.
  • DI-Agnostic Core: Decoupled from any specific DI container, with official support for Microsoft DI and Autofac.
  • Advanced Handler Filtering: Use tags and dynamic predicates to select which handlers run in a given context, enabling patterns like feature flags or environment-specific logic.

This guide covers the direct mapping of concepts for a smooth migration from MediatR. However, the true benefits of LiteBus are found in the features that go beyond basic mediation. To explore these capabilities in detail, the official Wiki provides in-depth guides on the Durable Command Inbox, advanced event concurrency, handler filtering, and other best practices.


This content originally appeared on DEV Community and was authored by A. Shafie


Print Share Comment Cite Upload Translate Updates
APA

A. Shafie | Sciencx (2025-11-12T00:11:57+00:00) Migrating from MediatR to LiteBus. Retrieved from https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/

MLA
" » Migrating from MediatR to LiteBus." A. Shafie | Sciencx - Wednesday November 12, 2025, https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/
HARVARD
A. Shafie | Sciencx Wednesday November 12, 2025 » Migrating from MediatR to LiteBus., viewed ,<https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/>
VANCOUVER
A. Shafie | Sciencx - » Migrating from MediatR to LiteBus. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/
CHICAGO
" » Migrating from MediatR to LiteBus." A. Shafie | Sciencx - Accessed . https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/
IEEE
" » Migrating from MediatR to LiteBus." A. Shafie | Sciencx [Online]. Available: https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/. [Accessed: ]
rf:citation
» Migrating from MediatR to LiteBus | A. Shafie | Sciencx | https://www.scien.cx/2025/11/12/migrating-from-mediatr-to-litebus/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.