One of the most underappreciated yet effective design patterns is the Chain of Responsibility, or CoR, pattern. Like ASP.NET Core middleware or HttpClient handlers, it enables us to create adaptable, extensible processing pipelines.

How .NET Uses Chain of Responsibility?

The CoR pattern is heavily used in .NET, especially in ASP.NET Core and HttpClient.

  • ASP.NET Core Middleware
    • Middleware components are chained together to process HTTP requests.
    • Each middleware can decide to process the request, pass it to the next middleware, or short-circuit the pipeline.
  • HttpClient Handlers
    • It uses a chain of HttpMessageHandler instances to process HTTP requests.
    • Each handler can modify the request, pass it to the next handler, or short-circuit the pipeline.
  • Validation Pipelines: Libraries like FluentValidation use a similar pattern to chain validation rules.

Delegate-Based CoR for Validation Rules
Instead of hardcoding validation logic, we dynamically add validation rules using delegate chaining.

Define the Delegate Pipeline with Short-Circuit support.

public class ValidationPipeline
{
    private Func<User, Task<bool>> _pipeline = user => Task.FromResult(true); // Default: Always passes
    public void AddRule(Func<User, Task<bool>> rule)
    {
        var previous = _pipeline;
        _pipeline = async user => await previous(user) && await rule(user); // Chain with AND condition
    }
    public async Task<bool> ValidateAsync(User user) => await _pipeline(user);
}


Dynamically Add Rules
Validate Pipeline
public class FeatureToggleService : IFeatureToggleService
{
    private readonly ValidationPipeline _validateRules;
    private readonly IFeatureManagerSnapshot _featureManager;
    public FeatureToggleService(IFeatureManagerSnapshot featureManager)
    {
        _validateRules = new ValidationPipeline();
        _featureManager = featureManager;
    }
    public async Task<bool> CanAccessFeatureAsync(User user)
    {
        _validateRules.AddRule(async user => await _featureManager.IsEnabledAsync("CustomGreeting"));
        _validateRules.AddRule(user => Task.FromResult(user.Role == "Amin"));
        _validateRules.AddRule(user => Task.FromResult(user.HasActiveSubscription));

        return await _validateRules.ValidateAsync(user);
    }
}
public interface IFeatureToggleService
{
    Task<bool> CanAccessFeatureAsync(User user);
}

How Can It Help?

  • Dynamic & Extensible: Add/remove rules without modifying existing logic.
  • Follows Open-Closed Principle (OCP): New rules can be added without modifying old code.
  • Composable: Chain rules like ASP.NET Core middleware.
  • Async-Support: Works well with async validation.  

HostForLIFE ASP.NET Core Hosting

European Best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.