前言

在前面的文章中,我们介绍了在业务层实现管道模式:

今天,我们同样使用IPipelineBehavior,介绍如何在业务层实现校验请求参数,用于检查输入是否满足业务要求。

Demo

首先,创建ASP.NET Core Web API项目,引用Nuget包:

MediatR
MediatR.Extensions.Microsoft.DependencyInjection
FluentValidation
FluentValidation.DependencyInjectionExtensions

1.实现IPipelineBehavior

创建ValidationBehaviour,用于校验请求参数:

public class ValidationBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IRequest<TResponse>
{
    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()) return await next();

        // 执行校验器
        var context = new ValidationContext<TRequest>(request);
        var validationResults =
            await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken)));
        var errors = validationResults.SelectMany(r => r.Errors).Where(f => f != null).ToList();

        if (!errors.Any()) return await next();

        // 返回错误
        var sb = new StringBuilder();
        errors.ForEach(f =>
        {
            sb.Append(f.ErrorMessage);
        });

        throw new Exception(sb.ToString());
    }
}

2.注册IPipelineBehavior

修改Startup.cs:

services.AddValidatorsFromAssembly(typeof(Startup).Assembly);

services.AddMediatR(typeof(Startup).Assembly);
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>))

3.测试

修改WeatherForecastController,使用Mediator:

public class WeatherForecastController : ControllerBase
{
    private readonly IMediator _mediator;

    public WeatherForecastController(IMediator mediator)
    {
        this._mediator = mediator;
    }

    [HttpGet]
    public async Task<IEnumerable<WeatherForecast>> Get(int count)
    {
        return await this._mediator.Send(new GetWeatherForecastQuery { Count= count });
    }
}

public class GetWeatherForecastQuery : IRequest<IEnumerable<WeatherForecast>>
{
    public int Count { get; set; }
}

internal class GetWeatherForecastQueryHandler : IRequestHandler<GetWeatherForecastQuery, IEnumerable<WeatherForecast>>

    public async Task<IEnumerable<WeatherForecast>> Handle(GetWeatherForecastQuery request, CancellationToken cancellationToken)
    {
        var rng = new Random();
        return Enumerable.Range(1, request.Count).Select(index => new WeatherForecast
        {
            TemperatureC = rng.Next(-20, 55),
        })
        .ToArray();
    }
}

并为GetWeatherForecastQuery创建一个Validator,校验Count参数的取值范围:

public class GetWeatherForecastQueryValidator : AbstractValidator<GetWeatherForecastQuery>
{
    public GetWeatherForecastQueryValidator()
    {
        RuleFor(c => c.Count)
            .GreaterThanOrEqualTo(1).WithMessage("Count的取值范围是1到5")
            .LessThanOrEqualTo(5).WithMessage("Count的取值范围是1到5");
    }
}

运行程序,输入错误值,将抛出异常:

图片

结论

在本文中,我们通过FluentValidation实现校验功能,详细使用方式请参看官网:https://fluentvalidation.net/

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“

来源:https://mp.weixin.qq.com/s/Ux_kAdFzzKSwdWM9XoE73A
点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部