Search code examples
c#asp.net.netmediatormediatr

Is there a way to skip MediatR Pipeline?


I would like to cache some responses from CommandsHandlers.

I Already did this using IPipelineBehaviour, but only 5% of my requests really must have cache, and the other 95% must skip this Pipeline. Is there a way to do that?

Below follows my code.

Thanks!

     public class PipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> 
                                         where TRequest : IRequest<TResponse>, IProvideCacheKey
    {
        private readonly IMemoryCache _cache;
        public PipelineBehavior(IMemoryCache cache)
        {
            _cache = cache;
        }
        public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, 
                                            RequestHandlerDelegate<TResponse> next)
        {
            // Check in cache if we already have what we're looking for
            var cacheKey = request.CacheKey;
            if (_cache.TryGetValue<TResponse>(cacheKey, out var cachedResponse))
            {
                return cachedResponse;
            }
            // If we don't, execute the rest of the pipeline, and add the result to the cache
            var response = await next();
            _cache.Set(cacheKey, response);
            return response;
        }
    }





     public class GetUserByEmailCommand : Command, IRequest<bool>, IProvideCacheKey
     {
        public string Email { get; set; }

        public string CacheKey =>  $"{GetType().Name}:{Email}";

        public override bool IsValid()
        {
            ValidationResult = new GetUserByEmailCommandValidation<GetUserByEmailCommand>().Validate(this);

            return ValidationResult.IsValid;
        }
    }



  public interface IProvideCacheKey
  {
        string CacheKey { get; }
  }

Solution

  • You can wrap your caching behavior in a check that is bypassed if the request is not cacheable to let the pipeline continue. In your case, you can probably just check if the request implements your interface at the start of the Handle method:

    if (request is IProvideCacheKey)
    {
       // perform cache behavior, return if cached and terminate the pipeline
    }
    // else continue the pipeline
    

    There's a couple good examples of this in more detail at:

    https://lurumad.github.io/cross-cutting-concerns-in-asp-net-core-with-meaditr

    https://anderly.com/2019/12/12/cross-cutting-concerns-with-mediatr-pipeline-behaviors/