Manikandan — Manikandan
Updated on 4 min read Manikandan Design Patterns

Mediator Design Pattern in .NET Core API

A practical Mediator pattern guide in C# with centralized and hierarchical coordination styles for clean .NET workflows.

A practical Mediator pattern guide in C# with centralized and hierarchical coordination styles for clean .NET workflows.

Intro

As application workflows grow, components can become tangled by calling each other directly. The Mediator pattern keeps that under control by moving communication into one coordinating object.

What Is the Mediator Pattern?

Mediator is a behavioral design pattern that centralizes communication between related objects so they do not depend on each other directly.

In .NET systems, it often appears in form workflows, dialog coordination, domain orchestration, and application services that coordinate multiple dependencies.

Mediator Class Example

The example below models an order checkout flow where the mediator coordinates inventory, payment, and confirmation steps.

public sealed record CheckoutRequest(Guid OrderId, decimal Amount);
public interface ICheckoutMediator
{
Task SubmitAsync(CheckoutRequest request, CancellationToken cancellationToken);
}
public sealed class CheckoutMediator(
IInventoryService inventory,
IPaymentService payment,
INotificationService notifications) : ICheckoutMediator
{
public async Task SubmitAsync(CheckoutRequest request, CancellationToken cancellationToken)
{
await inventory.ReserveAsync(request.OrderId, cancellationToken);
await payment.ChargeAsync(request.OrderId, request.Amount, cancellationToken);
await notifications.SendConfirmationAsync(request.OrderId, cancellationToken);
}
}

Why This Works

The mediator becomes the single place where collaboration rules live. Individual services stay focused on their own behavior while the mediator owns the order in which they are invoked.

When to Use It

Mediator is a strong fit when many components need to coordinate but should not know about one another.

  • coordinating multi-step form or wizard flows
  • orchestrating backend application services
  • reducing many-to-many object dependencies
  • centralizing UI dialog or screen interactions
  • keeping workflow changes out of individual services

If one object only talks to one other object, direct composition is usually simpler.

Important Note for ASP.NET Core

In ASP.NET Core, mediators are often implemented as application services or through dispatcher abstractions registered in DI. This keeps controllers thin and makes orchestration easier to test.

public interface ICommandMediator<TCommand>
{
Task HandleAsync(TCommand command, CancellationToken cancellationToken);
}
builder.Services.AddScoped<ICheckoutMediator, CheckoutMediator>();

This arrangement helps you add validation, logging, and retries around one coordination boundary instead of scattering them across controllers.

Core Components of the Pattern

PartPurposeExample in this article
MediatorCoordinates collaborationCheckoutMediator
ColleaguesWork through the mediatorinventory, payment, notification services
Request modelCarries workflow inputCheckoutRequest
ClientStarts the workflowcontroller or API endpoint

Common Mediator Variations

You will commonly apply the Mediator pattern in these two forms:

Centralized Mediator (Source)

A single mediator owns the full workflow and keeps all participants decoupled.

public sealed class OrderWorkflowMediator : ICheckoutMediator
{
public Task SubmitAsync(CheckoutRequest request, CancellationToken cancellationToken) => Task.CompletedTask;
}

Hierarchical Mediator (Source)

Multiple mediators coordinate sub-flows, each responsible for one layer of the workflow.

public interface IPaymentMediator
{
Task ChargeAsync(Guid orderId, decimal amount, CancellationToken cancellationToken);
}

How the Variations Differ

VariationCoordination modelComplexityBest use case
Centralized MediatorOne object owns the full workflowLowerSmall to medium orchestration
Hierarchical MediatorMultiple mediators split responsibilitiesHigherLarge workflows with clear subdomains

SOLID Principles Behind It

SRP - Single Responsibility Principle

Colleagues focus on one responsibility while the mediator focuses on coordination.

OCP - Open/Closed Principle

You can add new steps or participants without rewriting all peers.

DIP - Dependency Inversion Principle

Participants depend on mediator abstractions instead of hard-coded collaborators.

Advantages and Disadvantages

Advantages

  • reduces object-to-object coupling
  • centralizes orchestration logic
  • improves workflow testability
  • keeps participant classes small and focused

Disadvantages (and Optional Alternatives)

  • mediators can become large if they absorb too much logic Optional pattern: Facade (when the main goal is simpler access, not orchestration).
  • workflow changes may require touching the mediator more often than the colleagues Optional pattern: Chain of Responsibility (when steps can independently approve or reject).
  • deep coordination graphs can be harder to visualize Optional pattern: Observer (when the main need is event fan-out instead of orchestration).

UML Diagram

classDiagram
class Client
class ICheckoutMediator {
<<interface>>
+SubmitAsync(request)
}
class CheckoutMediator
class InventoryService
class PaymentService
class NotificationService
Client --> ICheckoutMediator
CheckoutMediator ..|> ICheckoutMediator
CheckoutMediator --> InventoryService
CheckoutMediator --> PaymentService
CheckoutMediator --> NotificationService

A Quick Usage Example

var request = new CheckoutRequest(Guid.NewGuid(), 250m);
await checkoutMediator.SubmitAsync(request, CancellationToken.None);

The caller triggers one coordination entry point while the mediator manages the collaboration details.

How to Validate the Pattern

Use these checks to confirm your Mediator implementation is healthy:

  • colleagues should not call each other directly
  • workflow ordering should live in the mediator, not in controllers
  • each mediator should stay focused on a single coordination boundary
  • tests should verify orchestration without requiring real upstream callers
  • you should be able to swap a colleague without changing all peers

Is there any other way to check our implementations

  • yes, add unit tests for the mediator workflow steps
  • add integration tests around DI registration and endpoint execution

Summary

The Mediator pattern keeps collaborative workflows focused and maintainable by moving conversation rules into a dedicated coordinator. In .NET APIs, it is especially useful when application services need to orchestrate several dependencies without creating a web of direct references.

Share:
Back to Blog

Related Posts

View All Posts »