Как подружить ValidationBehavior и LoggingBehavior в MediatR?

Прежде чем выполнить код в Handler, у меня есть два конвейера поведений:

LoggingBehavior

public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : class
    where TResponse : class
{
    public async Task<TResponse> Handle(TRequest request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {

        Serilog.Log.Information("Начало");

        TResponse result = await next();

        Serilog.Log.Information("Конец");

        return result;
    }
}

ValidationBehavior

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
    where TResponse : class
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;

    public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
    {
        _validators = validators;
    }

    public async Task<TResponse> Handle(
        TRequest request, 
        RequestHandlerDelegate<TResponse> next, 
        CancellationToken cancellationToken)
    {
        if(!_validators.Any())
        {
            return await next();
        }

        var errors = _validators
            .Select(validator => validator.Validate(request).ToString(";"))
            .Where(errors => errors != "")
            .Distinct()
            .ToList();

        if(errors.Any())
        {
            return new ObjectResult(errors) 
            {
                StatusCode = StatusCodes.Status400BadRequest,
            } as TResponse;
        }
        else
        {
            return await next();
        }
    }
}

Вот порядок их регистрации

builder.Services.AddScoped(
    typeof(IPipelineBehavior<,>),
    typeof(ValidationBehavior<,>));

builder.Services.AddScoped(
    typeof(IPipelineBehavior<,>),
    typeof(LoggingBehavior<,>));

При пройденной валидации идёт логирование, но при неудачно я возвращаю ошибку и дальше никуда не перехожу. Есть ли способ подружить эти конвейера, чтобы при неудачно валидации всё-равно было логирование но при этом код в Handler не выполнялся?

Я думал над созданием класс Result в котором будет свойство пройдена ли валидация, но тогда это свойство нужно будет проверять в Handler и это будет выглядеть как костыль.


Ответы (1 шт):

Автор решения: tiovi

У вас в ValidationBehavior возвращается ObjectResult если валидация не прошла успешно. Попробуйте возвращать null. Также сделайте проверку логгирования для ValidationBehavior. То есть, если он вернет null, то логгирование не выполняется.

Но! Использование дополнительного класса для передачи результата валидации не является костылем, поэтому можете реализовать и такой вариант.

→ Ссылка