feat(api): Доработка фильтра валидации

This commit is contained in:
Mikhail Trubnikov
2026-05-25 11:40:22 +10:00
parent ac363ff7fa
commit cb69be5528
3 changed files with 17 additions and 21 deletions

View File

@@ -49,9 +49,6 @@ namespace PARR.API.Infrastructure
// Включаем авто-валидацию FluentValidation для контроллеров // Включаем авто-валидацию FluentValidation для контроллеров
//services.AddFluentValidationAutoValidation(); //services.AddFluentValidationAutoValidation();
services.AddScoped<AsyncValidationFilter>();
return services; return services;
} }
} }

View File

@@ -1,19 +1,21 @@
using FluentValidation; using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using PARR.API.Contracts.V1.Responses.Base;
namespace PARR.API.Infrastructure.Filters namespace PARR.API.Infrastructure.Filters
{ {
/// <summary>
/// Фильтр для автоматического применения валидации реквестов.
/// </summary>
public class AsyncValidationFilter : IAsyncActionFilter public class AsyncValidationFilter : IAsyncActionFilter
{ {
private readonly IServiceProvider _serviceProvider; /// <summary>
/// Фильтр для автоматического применения валидации реквестов.
public AsyncValidationFilter(IServiceProvider serviceProvider) /// Выполняется до срабатывания метода в контроллере.
{ /// </summary>
_serviceProvider = serviceProvider; /// <param name="context"></param>
} /// <param name="next"></param>
/// <returns></returns>
/// <exception cref="ValidationException"></exception>
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{ {
foreach (var argument in context.ActionArguments.Values) foreach (var argument in context.ActionArguments.Values)
@@ -21,22 +23,20 @@ namespace PARR.API.Infrastructure.Filters
if (argument == null) if (argument == null)
continue; continue;
// Динамически ищем валидатор в DI для типа текущего аргумента
var validatorType = typeof(IValidator<>).MakeGenericType(argument.GetType()); var validatorType = typeof(IValidator<>).MakeGenericType(argument.GetType());
var validator = _serviceProvider.GetService(validatorType); var validator = context.HttpContext.RequestServices.GetService(validatorType) as IValidator;
if (validator is IValidator validatorInstance) if (validator is IValidator validatorInstance)
{ {
var validationContext = new ValidationContext<object>(argument); var validationContext = new ValidationContext<object>(argument);
var validationResult = await validatorInstance.ValidateAsync(validationContext, context.HttpContext.RequestAborted);
// Запуск асинхронной валидации
var validationResult = await validator.ValidateAsync(validationContext, context.HttpContext.RequestAborted);
if (!validationResult.IsValid) if (!validationResult.IsValid)
{ {
var errors = validationResult.Errors throw new ValidationException(validationResult.Errors);
.Select(e => new ErrorModel { Message = e.ErrorMessage })
.ToList();
context.Result = new BadRequestObjectResult(new Response(false, errors));
return;
} }
} }
} }

View File

@@ -11,7 +11,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Elastic.CommonSchema.Serilog" Version="8.19.0" /> <PackageReference Include="Elastic.CommonSchema.Serilog" Version="8.19.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.16" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.16" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.23.0" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" /> <PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />