diff --git a/.editorconfig b/.editorconfig index d894c777..579d7292 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ root = true [*] indent_style = space vsspell_section_id = cb4a4387061549238f01a4c2739f296e -vsspell_ignored_keywords_cb4a4387061549238f01a4c2739f296e = Mongo +vsspell_ignored_keywords_cb4a4387061549238f01a4c2739f296e = Mongo|validators # XML project files [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] @@ -141,4 +141,4 @@ csharp_preserve_single_line_blocks = true ############################### [*.vb] # Modifier preferences -visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion \ No newline at end of file +visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:suggestion diff --git a/Directory.Packages.props b/Directory.Packages.props index f156d20d..c763e539 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,6 +3,8 @@ + + diff --git a/src/API.Core/API.Core.csproj b/src/API.Core/API.Core.csproj index 2291f0dd..45374c69 100644 --- a/src/API.Core/API.Core.csproj +++ b/src/API.Core/API.Core.csproj @@ -8,6 +8,7 @@ + diff --git a/src/API.Core/Validators/ValidationBehavior.cs b/src/API.Core/Validators/ValidationBehavior.cs new file mode 100644 index 00000000..2c94ac80 --- /dev/null +++ b/src/API.Core/Validators/ValidationBehavior.cs @@ -0,0 +1,31 @@ +using FluentValidation; +using MediatR; + +namespace Fossa.API.Core.Validators; + +public class ValidationBehavior : IPipelineBehavior where TRequest : IRequest +{ + private readonly IEnumerable> _validators; + + public ValidationBehavior(IEnumerable> validators) + { + _validators = validators; + } + + public async Task Handle( + TRequest request, + RequestHandlerDelegate next, + CancellationToken cancellationToken) + { + if (_validators.Any()) + { + var context = new ValidationContext(request); + var validationResults = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken))).ConfigureAwait(false); + var failures = validationResults.SelectMany(r => r.Errors).Where(f => f != null).ToList(); + if (failures.Count != 0) + throw new ValidationException(failures); + } + + return await next().ConfigureAwait(false); + } +} diff --git a/src/API.Web/API.Web.csproj b/src/API.Web/API.Web.csproj index e97f4e34..ef40a05e 100644 --- a/src/API.Web/API.Web.csproj +++ b/src/API.Web/API.Web.csproj @@ -11,6 +11,7 @@ + diff --git a/src/API.Web/Program.cs b/src/API.Web/Program.cs index 4d242a0b..e8f5032a 100644 --- a/src/API.Web/Program.cs +++ b/src/API.Web/Program.cs @@ -1,6 +1,8 @@ using Autofac; using Autofac.Extensions.DependencyInjection; +using FluentValidation; using Fossa.API.Core; +using Fossa.API.Core.Validators; using Fossa.API.Infrastructure; using Fossa.API.Persistence; using Fossa.API.Web; @@ -51,17 +53,22 @@ builder.Services.AddFrameworkPlatform(); -builder.Services.AddMediatR(cfg => -{ - cfg.RegisterServicesFromAssemblies(Seq( +var assemblies = Seq( typeof(DefaultCoreModule), typeof(DefaultInfrastructureModule), typeof(DefaultPersistenceModule), typeof(DefaultWebModule)) .Map(x => x.Assembly) - .ToArray()); + .ToArray(); + +builder.Services.AddMediatR(cfg => +{ + cfg.RegisterServicesFromAssemblies(assemblies); + cfg.AddOpenBehavior(typeof(ValidationBehavior<,>)); }); +builder.Services.AddValidatorsFromAssemblies(assemblies); + builder.Services.Scan(scan => scan .FromApplicationDependencies() .AddClasses(classes => classes.AssignableTo(typeof(IMapper<,>)))