前言
在前面的文章中,我们介绍了在业务层实现管道模式:
今天,我们同样使用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
发表评论 取消回复