前言
在前面的文章中,我们介绍了在业务层实现管道模式:
响应缓存
记录请求日志
今天,我们同样使用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“