在业务层实现校验请求参数

前言

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

今天,我们同样使用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");
    }
}

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

f495abeb59d8e0220993a9f108c7b28e.png

结论

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值