Как реализовать валидацию (mediatR + FluentValidation) без исключения? - PullRequest
1 голос
/ 15 апреля 2020

В моем контроллере я использую шаблон-посредник для удаления свойства

public async Task<IActionResult> Delete(int propertyId)
    {
        await _mediator.Send(new DeletePropertyCommand(propertyId));

        return NoContent();
    }

Далее я проверяю DeletePropertyCommand, используя свободную проверку, которая проверяет, существует ли она в db

RuleFor(property => property).MustAsync(Exist).MustAsync(BeOwnedByCurrentUser);

Если беглая проверка обнаруживает какую-либо ошибку, она обрабатывается в конвейере mediatr - в настоящее время я генерирую исключение ValidationException, которое обрабатывается в глобальном классе ErrorHandler:

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

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

    public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {
        var context = new ValidationContext(request);

        var errors = _validators
            .Select(v => v.Validate(context))
            .SelectMany(result => result.Errors)
            .Where(f => f != null)
            .ToList();

        return !errors.Any() ? next() : throw new ValidationException(errors);
    }
}

Класс обработчика ошибок:

public class ErrorHandler
{
    private readonly RequestDelegate _next;
    public ErrorHandler(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception ex)
    {
        // if ex is of type ValidationException -> get errors, serialize them, return bad request
    }
}

То, что я ищу, это какой-то способ избежать создания исключений, которые стоят дорого и просто возвращают неверный ответ на запрос с соответствующими ошибками.

...