I'm trying to add a pipeline behavior on a base request that validates that the invoker has access to the tenant they are invoking against.
One way I found, is adding an interface ITenantRequest on some SomethingRequest and making a completely generic PipelineBehavior<,> that will be invoked on every single request and perform the validation if request is ITenantRequest.
That doesn't seems very efficient though and I'm wondering if I could make the pipeline run only on requests that are extending a base class with that property.
Here's the code that I wish worked, but it breaks with the following error message:
Implementation type 'TenantAccessValidationPipeline`2[SomeTenantRequest,SomeTenantResponse]' can't be converted to service type 'MediatR.IPipelineBehavior`2[SomeTenantRequest,SomeTenantResponse]'
Bootstrapping:
var services = new ServiceCollection();
services.AddMediatR(typeof(Program).Assembly);
services.AddScoped(typeof(IPipelineBehavior<,>),
typeof(TenantAccessValidationPipeline<,>));
var provider = services.BuildServiceProvider();
var mediator = provider.GetRequiredService<IMediator>();
mediator.Send(new SomeTenantRequest() {
SomeProperty = "SomeProperty", TenantId = "CustomerId" });
Classes:
public class RequestsBase<T> : IRequest<T>
{
public string TenantId { get; set; }
}
public class TenantAccessValidationPipeline<T, _>
: IPipelineBehavior<RequestsBase<T>, T>
{
public Task<T> Handle(RequestsBase<T> request, CancellationToken ct,
RequestHandlerDelegate<T> next)
{
Console.WriteLine(request.TenantId);
return next();
}
}
public record SomeTenantResponse(string p);
public class SomeTenantRequest : RequestsBase<SomeTenantResponse>
{
public string SomeProperty { get; set; }
}
public class SomeTenantRequestHandler
: IRequestHandler<SomeTenantRequest, SomeTenantResponse>
{
public Task<SomeTenantResponse> Handle(
SomeTenantRequest request, CancellationToken ct)
{
return Task.FromResult(
new SomeTenantResponse(request.TenantId + request.SomeProperty));
}
}