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

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在业务层实现校验请求参数相关的知识,希望对你有一定的参考价值。

前言

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

今天,我们同样使用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“

以上是关于在业务层实现校验请求参数的主要内容,如果未能解决你的问题,请参考以下文章

validation校验

自学有感9

SpringMVC 数据校验(JSR-303)

中间件

瞧瞧人家用SpringBoot写的后端API接口,那叫一个优雅

SpringMVC学习06SpringMVC中的数据校验