【问题标题】:FluentValidation inside a MediatR pipeline and Razor PagesMediatR 管道和 Razor 页面中的 FluentValidation
【发布时间】:2022-05-09 19:43:35
【问题描述】:

我正在做一个项目,所有事情都通过 mediatR 管道完成。

为了让事情变得简单,管道是这样的: -> 验证 -> 处理程序

验证层正在使用 FluentValidation,如果出现问题,则抛出 ValidationException。

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

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

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

            var validationResults = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken)));
            var failures = validationResults.SelectMany(r => r.Errors).Where(f => f != null).ToList();

            if (failures.Count != 0)
                throw new ValidationException(failures);
        }

        return await next();
    }
}

到目前为止一切正常。

现在,我的页面处理程序是这样的:

[BindProperty]
public LoginCommand Data { get; set; }

public async Task<IActionResult> OnPostAsync(CancellationToken cancellationToken)
{
    try
    {
        await _mediator.Send(Data, cancellationToken);
        return LocalRedirect("/Index");
    }
    catch (ValidationException ex)
    {
        var res = new ValidationResult(ex.Errors);
        res.AddToModelState(ModelState, nameof(Data));
        return Page();
    }
}

这样做很好,缺点是它为每个页面处理程序编写了大量代码。

有没有办法让处理程序看起来像这样:

[BindProperty]
public LoginCommand Data { get; set; }

public async Task<IActionResult> OnPostAsync(CancellationToken cancellationToken)
{
    await _mediator.Send(Data, cancellationToken);
    return LocalRedirect("/Index");
}

让这部分代码像过滤器/中间件一样随处可见

    try
    {
        // HANDLER CODE
    }
    catch (ValidationException ex)
    {
        var res = new ValidationResult(ex.Errors);
        res.AddToModelState(ModelState, nameof(VIEWMODEL_NAME));
        return Page();
    }

【问题讨论】:

  • 我和你一样,但我已经在 BaseController 中创建了方法 Send 并将这个逻辑放在一个地方。
  • 您不会在这里遇到LoginCommand 的属性与页面上的内容不匹配的问题吗?例如,验证器可以找到Name 的无效输入,但它实际上应该是Data.Name,因为AbstractValidator&lt;LoginCommand&gt; 不知道它是一个子对象,但不支持传入页面模型。我有这个问题。

标签: asp.net-core razor-pages fluentvalidation mediatr


【解决方案1】:

您可以在 MediatR 管道中的 ValidationPipelineBehavior 之前添加 ValidationExceptionPipelineBehavior

这将确保所有ValidationExceptions 都被捕获。

ExeptionPipelineBehavior 相当普遍。

【讨论】:

    猜你喜欢
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-15
    • 2018-01-26
    • 1970-01-01
    相关资源
    最近更新 更多