Closed kirnosenko closed 1 year ago
I did some investigation on this
It doesn't work for me with the setup as following
public class Command : IRequest {}
public class CommandHandler : IRequestHandler<Command> {/*...*/}
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger;
public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger)
{
_logger = logger;
}
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
_logger.LogInformation($"Handling {typeof(TRequest).Name}");
var response = await next();
_logger.LogInformation($"Handled {typeof(TResponse).Name}");
return response;
}
}
services.AddMediatR(cfg =>
{
cfg.AddOpenBehavior(typeof(LoggingBehavior<,>));
cfg.RegisterServicesFromAssembly(typeof(LoggingBehavior).Assembly);
});
Once I change my command and command handler to be as below it is working as expected
public class Command : IRequest<Unit> {}
public class CommandHandler : IRequestHandler<Command, Unit> {/*...*/}
MediatR version is 12.0.1 .NET 7.0.200 (ASPNET SDK)
Check the upgrade guide, your generic constraints are off.
Indeed, thanks and sorry for bothering
No worries, that was a huge but silent breaking change. Maybe I need an even bigger warning!
I think this page needs update https://github.com/jbogard/MediatR/wiki/Behaviors
If I understand the upgrade doc correctly behaviors should now have constraint where TRequest : notnull
. The example on the page still does where TRequest : IRequest<TResponse>
which was misleading to me
Check the upgrade guide, your generic constraints are off.
To save anyone the trip, here's the migration docs
Not sure what I am missing; I followed the migration guide, and still, pipeline behavior is not invoked, but handler works.
public class ValidationPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
builder.Services.AddMediatR(cfg => {
cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
cfg.AddBehavior(typeof(IPipelineBehavior<,>),typeof(ValidationPipelineBehavior<,>));
});
MediatR version is 12.0.1 .NET 6.0 MS DI
Please help me find what I'm missing and confirm that it was working prior to version 12.
Not sure what I am missing; I followed the migration guide, and still, pipeline behavior is not invoked, but handler works.
public class ValidationPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : notnull builder.Services.AddMediatR(cfg => { cfg.RegisterServicesFromAssembly(typeof(Program).Assembly); cfg.AddBehavior(typeof(IPipelineBehavior<,>),typeof(ValidationPipelineBehavior<,>)); });
MediatR version is 12.0.1 .NET 6.0 MS DI
Please help me find what I'm missing and confirm that it was working prior to version 12.
This code is valid, the bug, as far as I can tell, has nothing to do with its registration. Check your pipeline behavior for any early exists. I have recreated that in this gist. Have a look to see if there's any differences.
@isnakolah Thank you and it is working . The external interface which i created the IPipelineBehavior is caused the issue and it is not required.
If change:
public class GenericPipelineBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
- where TRequest : IRequest<TResponse>
+ where TRequest : notnull
{
then in Handle
method such code won't work.
IRequestHandler<TRequest, TResponse> handler = scope.ServiceProvider.GetRequiredService<IRequestHandler<TRequest, TResponse>>();
To fix this you can use:
Type handlerType = typeof(IRequest).IsAssignableFrom(typeof(TRequest))
? typeof(IRequestHandler<>).MakeGenericType(typeof(TRequest))
: typeof(IRequestHandler<,>).MakeGenericType(typeof(TRequest), typeof(TResponse));
object handler = scope.ServiceProvider.GetRequiredService(handlerType);
I just had a problem in the past days. I was implementing validations with Fluent Validations but the PipelineBehavior seemed not to work. So after a very very long journey, I made this change to my code:
From this:
where TRequest : IRequest<TResponse>
To this:
where TRequest : notnull
Also, need to say that I was implementing 2 types of commands: IRequest<TResponse>
and IRequest
. I've tried to use something like:
where TRequest : IRequest<TResponse>, IRequest
but to save you guys the work, if you've been trying that (just like me hehe), it will not work Hope this could help someone :)
@blackhawk64 with respect to supporting both IRequest<TResponse>
and IRequest
, you can constrain against IBaseRequest
which both of these types inherit.
i.e. where TRequest : IBaseRequest
@jacobjmarks Thank you very much, you saved my day being depressed.
Prior to 12 everything worked fine but now I can't make pipeline behaviors work. I register them like this: services.AddMediatR(c => { c.RegisterServicesFromAssembly(typeof(Startup).Assembly); c.AddOpenBehavior(typeof(LoggingBehaviour<,>)); c.AddOpenBehavior(typeof(ExceptionBehaviour<,>)); });
But no calls for them. The handler itself still works. What am I missing?