在Mediatr行为管道中进行验证

时间:2018-01-18 12:25:52

标签: c# unity-container fluentvalidation mediatr

我正在使用Mediatr 4和我的web api 2项目。与FluentValidation和Unity一起,我一直在添加管道行为来验证我的请求。

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 failures = _validators
            .Select(v => v.Validate(context))
            .SelectMany(result => result.Errors)
            .Where(f => f != null)
            .ToList();

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

这一切都运行正常,但我真的希望能够在一个包装的响应中返回验证。我正在努力做出这样的改变,要么让它编译,要么没有Unity抛出运行时解决问题。

我在考虑这样的事情:

public class CommandResult : IResponseBase
{
    private List<ValidationFailure> _validationFailures = new List<ValidationFailure>();
    private readonly string _correlationid;

    public CommandResult(string correlationid)
    {
        _correlationid = correlationid;
    }
    public bool IsSuccess => _validationFailures.Count == 0;

    public static implicit operator bool(CommandResult result)
    {
        return result.IsSuccess;
    }

    public void AddFailures(List<ValidationFailure> results)
    {
        _validationFailures = results;
    }

    public List<ValidationFailure> Failures => _validationFailures;

    public string CorrelationId => _correlationid;
}

在此基础上,我在行为中添加了一个约束:

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
    where TResponse : IResponseBase, new()

但是尝试返回一个CommandResult而不是抛出一个异常会给我类型转换问题,感觉我觉得它太复杂而且我遗漏了一些非常基本的东西。

2 个答案:

答案 0 :(得分:1)

让我为您的问题提出另一种方法。而不是管道使用自定义ActionFilterAttribute来在请求命中控制器之前执行验证,并且必须由mediatr路由。下面的示例使用Autofac作为容器,但我希望您能够理解并能够适当地修改代码。作为奖励 - 您的Mediatr请求或处理程序不需要进行任何更改。验证将在控制器操作被调用之前执行,执行将不再进行,直到您有有效请求为止。

<?php
     $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
     $fullname = $_POST['firstname'] . ' ' . $_POST['lastname'];
     echo str_replace("s", "5", $fullname);
?>

}

答案 1 :(得分:0)

两种类型的验证(至少

  1. 请求数据验证-验证接收到的HTTP请求是否包含正确格式的必需数据。例如电子邮件字段为必填字段,应为有效的电子邮件地址**

  2. 特定于域的验证-验证Command尝试应用于当前应用程序状态的修改是否在域预期中有效。例如电子邮件必须唯一。 电子邮件不应被列入黑名单

第一种验证类型进入ActionFilter

第二种验证类型进入IPipelineBehavior

Domain Command Patterns - Validation